home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / fsfile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  27.2 KB  |  905 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. // Implementation of file-based ITapeFileSystem.
  21. // Used by the editor to save to disk.
  22.  
  23. #ifdef EDITOR
  24.  
  25. // Work-around for Win16 precompiled header bug -- all .cpp files in
  26. // lib/layout have to include editor.h first. This file
  27. // doesn't even need editor.h.
  28. ////// Now it does, edt_StripUsernamePassword.
  29. #include "editor.h"
  30.  
  31. #include "fsfile.h"
  32.  
  33. #ifdef XP_MAC
  34. #include "xp_file_mac.h"
  35. #endif
  36.  
  37. //-----------------------------------------------------------------------------
  38. //  CFileBackup
  39. //
  40. // File backup and restore Object, only used by CTapeFSFile.
  41. //
  42. //-----------------------------------------------------------------------------
  43. class CFileBackup {
  44. private:
  45.     XP_Bool m_bInitOk;
  46.     char *m_pBackupName;
  47.     char *m_pFileName;
  48.  
  49. public:
  50.     CFileBackup(): m_bInitOk(FALSE), m_pBackupName(0), m_pFileName(0){}
  51.  
  52.     ~CFileBackup(){
  53.         Reset();
  54.     }
  55.  
  56.     void Reset();
  57.     XP_Bool InTransaction(){ return m_bInitOk; }
  58.     ED_FileError BeginTransaction( char *pDestURL );
  59.     char* FileName(){ return m_pFileName; }
  60.     void Commit();
  61.     void Rollback();
  62. };
  63.  
  64.  
  65. void CFileBackup::Reset(){
  66.     if( m_pBackupName ){
  67.         XP_FREE( m_pBackupName );
  68.         m_pBackupName = 0;
  69.     }
  70.     if( m_pFileName ){
  71.         XP_FREE( m_pFileName );
  72.         m_pFileName = 0;
  73.     }
  74.     m_bInitOk = FALSE;
  75. }
  76.  
  77. ED_FileError CFileBackup::BeginTransaction( char *pDestURL ){
  78.     XP_StatStruct statinfo;
  79.  
  80.     if ( pDestURL == NULL || XP_STRLEN(pDestURL) == 0 || 
  81.              !NET_IsLocalFileURL(pDestURL) ) {
  82.         return ED_ERROR_BAD_URL;
  83.     }
  84.     
  85.     // Skip past the "file://" in pDestURL
  86.     m_pFileName = NET_ParseURL(pDestURL,GET_PATH_PART);
  87.     if (!m_pFileName) {
  88.       return ED_ERROR_CREATE_BAKNAME;
  89.     }
  90.     if (XP_Stat(m_pFileName, &statinfo, xpURL) != -1) {
  91.       if ( XP_STAT_READONLY( statinfo ) ){
  92.           return ED_ERROR_READ_ONLY;
  93.       }
  94.  
  95.       // File exists - rename to backup to protect data
  96.       m_pBackupName = XP_BackupFileName(pDestURL);
  97.       if ( m_pBackupName == NULL ) {
  98.           return ED_ERROR_CREATE_BAKNAME;
  99.       }
  100.       // Delete backup file if it exists
  101.       if ( -1 != XP_Stat(m_pBackupName, &statinfo, xpURL) &&
  102.             statinfo.st_mode & S_IFREG ) {
  103.           if ( 0 != XP_FileRemove(m_pBackupName, xpURL) ) {
  104.               return ED_ERROR_DELETE_BAKFILE;
  105.           }
  106.       }
  107.       if ( 0 != XP_FileRename(m_pFileName, xpURL, 
  108.                               m_pBackupName, xpURL) ){
  109.           return ED_ERROR_FILE_RENAME_TO_BAK;
  110.       }
  111.     }
  112.     // else file doesn't already exist, so no worries.
  113.  
  114.     m_bInitOk = TRUE;
  115.     return ED_ERROR_NONE;
  116. }
  117.  
  118.  
  119. void CFileBackup::Commit() {
  120.     XP_ASSERT( m_bInitOk );
  121.  
  122. #ifdef XP_UNIX
  123.     XP_StatStruct statinfo;
  124.  
  125.     if (m_pBackupName != NULL && m_pFileName != NULL &&
  126.         XP_Stat(m_pBackupName, &statinfo, xpURL) != -1) {
  127.         
  128.         /*
  129.          *    Is there an XP_chmod()? I cannot find one. This will
  130.          *    work for Unix, which is probably the only place that cares.
  131.          *    Don't bother to check the return status, as it's too late to
  132.          *    do anything about, and we are not in dire straights if it fails.
  133.          *    Bug #28775..djw
  134.          */
  135.         chmod(m_pFileName, statinfo.st_mode);
  136.     }
  137. #endif
  138.  
  139. #ifdef XP_MAC
  140.     // Mac needs to duplicate the resource fork of the old file into new location
  141.     // when there is a save or saveas; this preserves CKID rsrc among other things
  142.     if ( m_pBackupName != NULL && m_pFileName != NULL )
  143.         int result = XP_FileDuplicateResourceFork( m_pBackupName, xpURL,
  144.                                             m_pFileName, xpURL );
  145. #endif
  146.  
  147.     XP_FileRemove(m_pBackupName, xpURL);
  148. }
  149.  
  150. void CFileBackup::Rollback(){
  151.     XP_ASSERT( m_bInitOk );
  152.     if ( m_pBackupName ) {
  153.         // Restore previous file
  154.         // If this fails, we're really messed up!
  155.         XP_FileRemove(m_pFileName, xpURL);
  156.         XP_FileRename(m_pBackupName, xpURL, m_pFileName, xpURL);
  157.     }
  158. }
  159.  
  160. //-------------------------------------------------------------------------------
  161. // CTapeFSFile: File-based version of abstract file system
  162. //-------------------------------------------------------------------------------
  163. CTapeFSFile::CTapeFSFile(char *pDestPathURL,char *pDestURL):
  164.     m_pSrcBaseURL(0)
  165. {
  166.     XP_ASSERT(pDestPathURL && pDestURL);    
  167.     m_pDestPathURL = XP_STRDUP(pDestPathURL);
  168.     m_pDestURL = XP_STRDUP(pDestURL);
  169.     XP_ASSERT(m_pDestPathURL && m_pDestURL);    
  170. }
  171.  
  172. CTapeFSFile::~CTapeFSFile()
  173. {
  174.     ///// TODO DELETE TEMP FILES
  175.  
  176.     int i;        
  177.     for (i = 0; i < m_srcURLs.Size(); i++) {
  178.         if (m_srcURLs[i]) 
  179.             XP_FREE(m_srcURLs[i]);        
  180.     }
  181.     for (i = 0; i < m_destFilenames.Size(); i++) {
  182.         if (m_destFilenames[i])
  183.             XP_FREE(m_destFilenames[i]);
  184.     }
  185.     for (i = 0; i < m_streamOuts.Size(); i++) {
  186.         if (m_streamOuts[i])  // really don't need to check for NULL with C++ delete
  187.             delete m_streamOuts[i];
  188.     }
  189.     for (i = 0; i < m_fileBackups.Size(); i++) {
  190.         if (m_fileBackups[i])  // really don't need to check for NULL with C++ delete
  191.             delete m_fileBackups[i];
  192.     }
  193.  
  194.     if (m_pDestPathURL)
  195.         XP_FREE(m_pDestPathURL);
  196.     if (m_pDestURL)    
  197.         XP_FREE(m_pDestURL);
  198.     if (m_pSrcBaseURL)
  199.         XP_FREE(m_pSrcBaseURL);
  200. }
  201.  
  202. void CTapeFSFile::CopyURLInfo(intn, const URL_Struct *) 
  203. }
  204.  
  205. intn CTapeFSFile::GetType() {
  206.   return ITapeFileSystem::File;
  207. }
  208.  
  209. void CTapeFSFile::SetSourceBaseURL(char *pURL){
  210.     // Shouldn't pass in NULL, and m_pSrcBaseURL shouldn't already exist.
  211.     if (m_pSrcBaseURL || !pURL) {
  212.         XP_ASSERT(0);  
  213.         return;
  214.     }
  215.  
  216.     m_pSrcBaseURL = XP_STRDUP(pURL);
  217. }
  218.  
  219. intn CTapeFSFile::AddFile(char *pURL, char *, int16) {
  220.     // MIME type and char set are ignored.
  221.  
  222.     // Make pSrcURL absolute if SetSourceBaseURL() was called.
  223.     char *pSrcURL;
  224.     if (m_pSrcBaseURL)
  225.         pSrcURL =  NET_MakeAbsoluteURL(m_pSrcBaseURL,pURL);
  226.     else
  227.         pSrcURL = XP_STRDUP(pURL);
  228.  
  229.     if (!pSrcURL)
  230.         return ITapeFileSystem::Error;
  231.     
  232.     // First file added is the root HTML document, it's destination filename was passed in to
  233.     // the constructor of CTapeFSFile.
  234.     XP_Bool use_m_pDestURL = (m_srcURLs.Size() == 0);
  235.  
  236.     // Compute and store relative destination filename.
  237.     char *pDestFilename;
  238.     if (use_m_pDestURL) {
  239.         // Kind of redundant, here we are stripping the path, only to put it back on in CTapeFSFile::OpenStream().
  240.         pDestFilename = FE_URLToLocalName(m_pDestURL);
  241.     }
  242.     else {
  243.         pDestFilename =  FE_URLToLocalName(pSrcURL);
  244.     }
  245.     if (!pDestFilename) {
  246.         XP_FREE(pSrcURL);
  247.         return ITapeFileSystem::Error;
  248.     }
  249.  
  250.     // Check if source and destination are the same. 
  251.     // It's ok for the root HTML document to have the same source and dest.
  252.     //
  253.     // pSrcURL is absolute
  254.     if (!use_m_pDestURL && EDT_IsSameURL(pSrcURL,pDestFilename,NULL,m_pDestURL)) {
  255.         XP_FREE(pSrcURL);
  256.         XP_FREE(pDestFilename);
  257.         return ITapeFileSystem::SourceDestSame;
  258.     }
  259.  
  260.     // See if pSrcURL is already in the list.
  261.     int i = 0;
  262.     while( i < m_srcURLs.Size() ){
  263.         if( EDT_IsSameURL( pSrcURL, m_srcURLs[i], NULL, NULL ) ){
  264.             XP_FREE(pSrcURL);
  265.             XP_FREE(pDestFilename);
  266.             return i;
  267.         }
  268.         i++;
  269.     }
  270.  
  271.     // Add to lists.
  272.     int ret = m_srcURLs.Add(pSrcURL);
  273.     m_destFilenames.Add(pDestFilename);
  274.     // Keep m_streamOuts and m_fileBackups the same size as the others.
  275.     m_streamOuts.Add(NULL);
  276.     m_fileBackups.Add(NULL);
  277.     return ret;
  278. }
  279.  
  280. char* CTapeFSFile::GetSourceURL(intn iFileIndex) {
  281.     if (iFileIndex >= 0 && iFileIndex < m_srcURLs.Size()) {
  282.         return XP_STRDUP(m_srcURLs[iFileIndex]);
  283.     }
  284.     else {
  285.         XP_ASSERT(0);
  286.         return NULL;
  287.     }
  288. }
  289.  
  290. char* CTapeFSFile::GetDestAbsURL() {
  291.   return XP_STRDUP(m_pDestURL);
  292. }
  293.  
  294. char *CTapeFSFile::GetDestURL(intn iFileIndex) {
  295.     if (iFileIndex >= 0 && iFileIndex < m_destFilenames.Size()) {
  296.         return XP_STRDUP(m_destFilenames[iFileIndex]);
  297.     }
  298.     else {
  299.         XP_ASSERT(0);
  300.         return NULL;
  301.     }
  302. }
  303.  
  304. char *CTapeFSFile::GetDestPathURL() {
  305.     return XP_STRDUP(m_pDestPathURL);
  306. }
  307.  
  308. XP_Bool CTapeFSFile::IsLocalPersistentFile(intn) {
  309.     return TRUE;
  310. }
  311.  
  312. XP_Bool CTapeFSFile::FileExists(intn iFileIndex) {
  313.     // Check iFileIndex
  314.     if (iFileIndex < 0 || iFileIndex >= m_destFilenames.Size()) {
  315.         XP_ASSERT(0);
  316.         return FALSE;    
  317.     }
  318.  
  319.     char *pLocalName = PR_smprintf( "%s%s", m_pDestPathURL, m_destFilenames[iFileIndex]);
  320.      if (!pLocalName) {
  321.         XP_ASSERT(0);
  322.         return FALSE;
  323.     }
  324.  
  325.     // Get everything after "file://"
  326.     char *pxpURL = NET_ParseURL(pLocalName,GET_PATH_PART);
  327.     XP_FREE(pLocalName);
  328.     if (!pxpURL) {
  329.       XP_ASSERT(0);
  330.       return FALSE;
  331.     }
  332.     
  333.     XP_StatStruct statinfo;
  334.     Bool result = 
  335.       ( -1 != XP_Stat(pxpURL, &statinfo, xpURL) && statinfo.st_mode & S_IFREG );
  336.     XP_FREE(pxpURL);
  337.     return result;
  338. }
  339.  
  340. IStreamOut *
  341. CTapeFSFile::OpenStream( intn iFileIndex ) {
  342.     // Check iFileIndex
  343.     if (iFileIndex < 0 || iFileIndex >= m_destFilenames.Size()) {
  344.         XP_ASSERT(0);
  345.         return NULL;    
  346.     }
  347.  
  348.     // Create fileBackup object
  349.     XP_ASSERT( m_fileBackups[iFileIndex] == NULL ); // Shouldn't already exist.
  350.     m_fileBackups[iFileIndex]= new CFileBackup;
  351.     m_fileBackups[iFileIndex]->Reset();
  352.     char *pDestURL = PR_smprintf( "%s%s", m_pDestPathURL, m_destFilenames[iFileIndex]);
  353.     if ( !pDestURL ) {
  354.         XP_ASSERT(0);
  355.         return NULL;
  356.     }
  357.     ED_FileError status = m_fileBackups[iFileIndex]->BeginTransaction( pDestURL );
  358.     if( status != ED_ERROR_NONE ){
  359.         XP_FREE(pDestURL);        
  360.         return NULL;
  361.     }
  362.  
  363.     // Get path part of URL, e.g. without file://, for everything that uses xpURL
  364.     char *pDestPath = NET_ParseURL(pDestURL,GET_PATH_PART);
  365.     XP_FREE(pDestURL);        
  366.     if (!pDestPath) {
  367.         XP_ASSERT(0);
  368.         return NULL; 
  369.     }
  370.     
  371.     XP_File outFile = 0;
  372.     // First file is text, rest are binary.
  373.     // Right, well now the first file may be text or binary. This is still
  374.     // bogus-- each file should have a flag telling it's time, but I don't
  375.     // have time to redesign the #!$#@!#!@$ editor.
  376.     XP_FilePerm filePerm = ((iFileIndex == 0) && (!IsFirstBinary())) ? 
  377.                 XP_FILE_TRUNCATE : XP_FILE_TRUNCATE_BIN;
  378.     outFile = XP_FileOpen(pDestPath, xpURL, filePerm );
  379.     XP_FREE(pDestPath);
  380.  
  381.     if( outFile == 0 ){
  382.         return NULL;
  383.     }
  384.  
  385.  
  386.     // Now open a stream to outFile.
  387.     //    
  388.     // First file is text, rest are binary.
  389.     CStreamOutFile *streamOut = new CStreamOutFile(outFile,iFileIndex == 0 ? FALSE : TRUE);
  390.     XP_ASSERT(streamOut);    
  391.  
  392.     XP_ASSERT(m_streamOuts[iFileIndex] == NULL);  // not already set
  393.     // Store stream for later.
  394.     m_streamOuts[iFileIndex] = streamOut;
  395.  
  396.     return streamOut;    
  397. }    
  398.  
  399. void CTapeFSFile::CloseStream( intn iFileIndex ) {
  400.     if (iFileIndex < 0 || iFileIndex >= m_streamOuts.Size() || !m_streamOuts[iFileIndex]) {
  401.         XP_ASSERT(0);
  402.         return;
  403.     }
  404.  
  405.     delete m_streamOuts[iFileIndex];
  406.     m_streamOuts[iFileIndex] = NULL;
  407. }
  408.  
  409. void CTapeFSFile::Complete( XP_Bool bSuccess,
  410.                                                 EDT_ITapeFileSystemComplete *pfComplete, void *pArg ) {
  411.     // Commit or rollback all file changes, depending on the value of bSuccess.
  412.     int i;
  413.     for ( i = 0; i < m_fileBackups.Size(); i++ ) {
  414.         if ( !m_fileBackups[i] ) {
  415.             continue;
  416.         }
  417.         if ( m_fileBackups[i]->InTransaction() ) {
  418.             if ( bSuccess )
  419.                 m_fileBackups[i]->Commit();
  420.             else
  421.                 m_fileBackups[i]->Rollback();
  422.         }
  423.     }    
  424.  
  425.     if (pfComplete) {
  426.         pfComplete(TRUE,pArg);
  427.     }
  428.     delete this;
  429. }
  430.  
  431. //-------------------------------------------------------------------------------
  432. // CTapeFSPublish: Remote HTTP publish version of abstract file system
  433. //-------------------------------------------------------------------------------
  434. CTapeFSPublish::CTapeFSPublish(MWContext *pMWContext, char *pRemoteURL,
  435.                     char *pUsername, char *pPassword, char *pTempDir)  :
  436. m_iVerifier(iVerifierKey),
  437. m_pSrcBaseURL(NULL),
  438. m_pRemoteURL(XP_STRDUP(pRemoteURL)),
  439. m_pUsername(pUsername ? XP_STRDUP(pUsername) : 0),
  440. m_pPassword(pPassword ? XP_STRDUP(pPassword) : 0),
  441. m_pArg(0),
  442. m_pfComplete(0),
  443. m_bIsHTTP(FALSE),
  444. m_pTempDir(XP_STRDUP(pTempDir))
  445. {
  446.     m_pMWContext = pMWContext; 
  447.     XP_ASSERT( m_pRemoteURL && pMWContext );    
  448.     // m_pTempDir must end in a slash.
  449.     XP_ASSERT(m_pTempDir && *m_pTempDir && m_pTempDir[XP_STRLEN(m_pTempDir)-1] == '/');
  450.  
  451.     int type = NET_URL_Type(pRemoteURL);
  452.     if (type == FTP_TYPE_URL) {
  453.         m_bIsHTTP = FALSE;            
  454.     }
  455.     else if (type == HTTP_TYPE_URL || type == SECURE_HTTP_TYPE_URL) {
  456.         m_bIsHTTP = TRUE;            
  457.     }
  458.     else {
  459.         XP_ASSERT(0);
  460.     }
  461. }
  462.  
  463. CTapeFSPublish::~CTapeFSPublish() {
  464.     XP_FREEIF(m_pSrcBaseURL);
  465.  
  466.     int i;        
  467.     for (i = 0; i < m_srcURLs.Size(); i++) {
  468.        XP_FREEIF(m_srcURLs[i]);        
  469.     }
  470.  
  471.     XP_FREEIF(m_pRemoteURL);
  472.     XP_FREEIF(m_pUsername);
  473.     XP_FREEIF(m_pPassword);
  474.  
  475.     for (i = 0; i < m_remoteURLs.Size(); i++) {
  476.       XP_FREEIF(m_remoteURLs[i]);        
  477.     }
  478.  
  479.     XP_FREEIF(m_pTempDir);
  480.     for (i = 0; i < m_tempFilenames.Size(); i++) {
  481.         if (m_tempFilenames[i]) {
  482.             // Delete temp files.
  483.             XP_FileRemove(m_tempFilenames[i], xpFileToPost);
  484.             XP_FREE(m_tempFilenames[i]);
  485.         }
  486.     }
  487.  
  488.     for (i = 0; i < m_streamOuts.Size(); i++) {
  489.         if (m_streamOuts[i])  // really don't need to check for NULL with C++ delete
  490.             delete m_streamOuts[i];
  491.     }
  492. }
  493.  
  494. void CTapeFSPublish::CopyURLInfo(intn, const URL_Struct *) 
  495. }
  496.  
  497. intn CTapeFSPublish::GetType() {
  498.   return ITapeFileSystem::Publish;
  499. }
  500.  
  501. // Some random value.
  502. int32 CTapeFSPublish::iVerifierKey = 0xABACADAE;
  503.  
  504. void CTapeFSPublish::SetSourceBaseURL(char *pURL){
  505.     // Shouldn't pass in NULL, and m_pSrcBaseURL shouldn't already exist.
  506.     if (m_pSrcBaseURL || !pURL) {
  507.         XP_ASSERT(0);  
  508.         return;
  509.     }
  510.     m_pSrcBaseURL = XP_STRDUP(pURL);
  511. }
  512.  
  513. intn CTapeFSPublish::AddFile(char *pURL, char *, int16) {
  514.     // MIME type and char set are ignored.
  515.  
  516.     // Make pSrcURL absolute if SetSourceBaseURL() was called.
  517.     char *pSrcURL;
  518.     if (m_pSrcBaseURL)
  519.         pSrcURL =  NET_MakeAbsoluteURL(m_pSrcBaseURL,pURL);
  520.     else
  521.         pSrcURL = XP_STRDUP(pURL);
  522.  
  523.     if (!pSrcURL)
  524.         return ITapeFileSystem::Error;
  525.     
  526.     // See if pSrcURL is already in the list.
  527.     int i = 0;
  528.     while( i < m_srcURLs.Size() ){
  529.         if( EDT_IsSameURL( pSrcURL, m_srcURLs[i], NULL, NULL)){
  530.             XP_FREE(pSrcURL);
  531.             return i;
  532.         }
  533.         i++;
  534.     }
  535.  
  536.     // Note that the way pNewRemoteURL is constructed has the desirable
  537.     // side effect of NOT copying in any username/password information 
  538.     // in pURL.
  539.     char *pNewRemoteURL = NULL;
  540.     if (m_srcURLs.Size() == 0)
  541.         // First file added is the root HTML document.    
  542.         pNewRemoteURL = XP_STRDUP(m_pRemoteURL);
  543.  
  544.     else {
  545.         // All others are images that will be placed in the directory of the root doc.    
  546.         pNewRemoteURL = makeLocal(m_pRemoteURL,pSrcURL);
  547.  
  548.     }
  549.     if ( !pNewRemoteURL ) {
  550.         XP_FREE(pSrcURL);
  551.         return ITapeFileSystem::Error;
  552.     }
  553.  
  554.     // Check if would be copying from one location to itself.
  555.     if (m_srcURLs.Size() > 0 && // Make sure not the root document.
  556.         EDT_IsSameURL(pSrcURL,pNewRemoteURL,NULL,m_pRemoteURL)) {
  557.       XP_FREE(pSrcURL);
  558.       XP_FREE(pNewRemoteURL);
  559.       return ITapeFileSystem::SourceDestSame;
  560.     }
  561.  
  562.     // Add to lists.
  563.     int ret = m_srcURLs.Add(pSrcURL);
  564.     m_remoteURLs.Add(pNewRemoteURL);
  565.     // Keep the same size as the other arrays..
  566.     m_tempFilenames.Add(NULL);
  567.     m_streamOuts.Add(NULL);
  568.     return ret;
  569. }
  570.  
  571. char* CTapeFSPublish::GetSourceURL(intn iFileIndex) {
  572.     if (iFileIndex >= 0 && iFileIndex < m_srcURLs.Size()) {
  573.         return XP_STRDUP(m_srcURLs[iFileIndex]);
  574.     }
  575.     else {
  576.         XP_ASSERT(0);
  577.         return NULL;
  578.     }
  579. }
  580.  
  581. char* CTapeFSPublish::GetDestAbsURL() {
  582.   return XP_STRDUP(m_pRemoteURL);
  583. }
  584.  
  585. char *CTapeFSPublish::GetUsername() {
  586.   return m_pUsername ? XP_STRDUP(m_pUsername) : 0;
  587. }
  588.  
  589. char *CTapeFSPublish::GetPassword() {
  590.   return m_pPassword ? XP_STRDUP(m_pPassword) : 0;
  591. }
  592.  
  593. char *CTapeFSPublish::GetDestURL(intn iFileIndex) {
  594.     if (iFileIndex >= 0 && iFileIndex < m_remoteURLs.Size()) {
  595.         // Find last slash.
  596.         char *slash = XP_STRRCHR(m_remoteURLs[iFileIndex],'/');
  597.         if (!slash) {
  598.             XP_ASSERT(0);
  599.             return NULL;
  600.         }
  601.         // Copy everything after the slash.
  602.         return XP_STRDUP(slash + 1);
  603.     }
  604.     else {
  605.         XP_ASSERT(0);
  606.         return NULL;
  607.     }
  608. }
  609.  
  610. char *CTapeFSPublish::GetDestPathURL() {
  611.     // Grab everything before and including the last slash in m_pRemoteURL.
  612.     char *slash = XP_STRRCHR(m_pRemoteURL,'/');
  613.     if (!slash) {
  614.         XP_ASSERT(0);
  615.         return NULL;
  616.     }
  617.  
  618.     char tmp = *(slash + 1);
  619.     *(slash + 1) = '\0';
  620.     char *ret = XP_STRDUP(m_pRemoteURL);
  621.     *(slash + 1) = tmp;
  622.     return ret;
  623. }
  624.  
  625. XP_Bool CTapeFSPublish::IsLocalPersistentFile(intn /* iFileIndex */) {
  626.     return FALSE;
  627. }
  628.  
  629. IStreamOut *
  630. CTapeFSPublish::OpenStream( intn iFileIndex ) {
  631.     // Check iFileIndex
  632.     if (iFileIndex < 0 || iFileIndex >= m_tempFilenames.Size()) {
  633.         XP_ASSERT(0);
  634.         return NULL;    
  635.     }
  636.  
  637.  
  638.     // WARNING: We are pulling a fast one here, m_pTempDir is xpURL and we treat it as xpFileToPost.
  639.     // Since there are no routines to convert a filename to xpFileToPost, I just take advantage of 
  640.     // it being the same as xpURL.
  641.  
  642.     // Get filename of temporary file.
  643.     // Use the temporary file of the current document.
  644.     // Start filename with "pub" so it doesn't collide with CEditCommandLog::CreateDocTempFilename()
  645.     // which starts all filenames with "edt" by default.  
  646.     char *pTempFilename = PR_smprintf("%spubl%d.tmp",m_pTempDir,(int)iFileIndex); // m_pTempDir ends in slash.
  647.     if (!pTempFilename) {
  648.       return NULL;
  649.     }
  650.     m_tempFilenames[iFileIndex] = pTempFilename;
  651.  
  652.  
  653.     XP_File outFile = 0;
  654.     // First file is text, rest are binary.
  655.     // Right, well now the first file may be text or binary. This is still
  656.     // bogus-- each file should have a flag telling it's time, but I don't
  657.     // have time to redesign the #!$#@!#!@$ editor.
  658.     XP_FilePerm filePerm = ((iFileIndex == 0) && (!IsFirstBinary())) ? 
  659.                 XP_FILE_TRUNCATE : XP_FILE_TRUNCATE_BIN;
  660.      outFile = XP_FileOpen(m_tempFilenames[iFileIndex],
  661.                  xpFileToPost, filePerm );
  662.  
  663.     XP_TRACE(("XP_FileOpen handle = %d", outFile));
  664.     
  665.     if( outFile == 0 ){
  666.         XP_TRACE(("Failed to opened file %s", m_tempFilenames[iFileIndex]));
  667.  
  668.         // Delete and clear temp filename, this serves as a flag to 
  669.         // Complete() that this entry should not be published.
  670.         XP_FREEIF(m_tempFilenames[iFileIndex]);
  671.         return NULL;
  672.     }
  673.  
  674.     // Now open a stream to outFile.
  675.     //    
  676.     // First file is text, rest are binary.
  677.     CStreamOutFile *streamOut = new CStreamOutFile(outFile,iFileIndex == 0 ? FALSE : TRUE);
  678.     if (!streamOut) {
  679.       // Out of memory.
  680.       XP_ASSERT(0);
  681.       return NULL;
  682.     }
  683.  
  684.     XP_ASSERT(m_streamOuts[iFileIndex] == NULL);  // not already set
  685.     // Store stream for later.
  686.     m_streamOuts[iFileIndex] = streamOut;
  687.  
  688.     return streamOut;    
  689. }    
  690.  
  691. void CTapeFSPublish::CloseStream( intn iFileIndex ) {
  692.     if (iFileIndex < 0 || iFileIndex >= m_streamOuts.Size() || !m_streamOuts[iFileIndex]) {
  693.         XP_ASSERT(0);
  694.         return;
  695.     }
  696.  
  697.     if (m_streamOuts[iFileIndex]->Status() != IStreamOut::EOS_NoError) {
  698.         // Delete and clear temp filename, this serves as a flag to 
  699.         // Complete() that this entry should not be published.
  700.         XP_FREEIF(m_tempFilenames[iFileIndex]);
  701.     }
  702.  
  703.     delete m_streamOuts[iFileIndex];
  704.     m_streamOuts[iFileIndex] = NULL;
  705. }
  706.  
  707. #if defined(XP_OS2)
  708. extern "C"
  709. #else
  710. PRIVATE
  711. #endif
  712. void edt_CTapeFSExit( URL_Struct *pURL, int status, MWContext * ) {
  713.     CTapeFSPublish *tapeFS = (CTapeFSPublish *)pURL->fe_data;
  714.     // Make sure that fe_data can be trusted.
  715.     if (!(tapeFS && tapeFS->Verify())) {
  716.         XP_ASSERT(0);
  717.         return;
  718.     }
  719.  
  720.     // Call complete function passed into CTapeFSPublish::Complete().
  721.     if (tapeFS->m_pfComplete) {
  722.         XP_Bool bSuccess = (status >= 0 && 
  723.             (pURL->server_status == 204 || pURL->server_status == 201 ||  // from HTTP
  724.              pURL->server_status == 0)); // from FTP.
  725.         tapeFS->m_pfComplete(bSuccess,tapeFS->m_pArg);
  726.     }
  727.     
  728.     // Kill the tapeFS.
  729.     delete tapeFS;
  730.  }
  731.  
  732. void CTapeFSPublish::Complete(XP_Bool bSuccess, 
  733.        EDT_ITapeFileSystemComplete *pfComplete, void *pArg ) {
  734.     m_pfComplete = pfComplete;
  735.     m_pArg = pArg;
  736.  
  737.  
  738.     // Count number of files we're actually publishing, may be less than 
  739.     // m_tempFilenames.Size() if errors occurred.
  740.     int numFilesToPost = 0;
  741.     for (int n = 0; n < m_tempFilenames.Size(); n++) {
  742.       if (m_tempFilenames[n])
  743.         numFilesToPost++;
  744.     }
  745.  
  746.  
  747.     // Publish temp files.  Temp files deleted in destructor.
  748.     if (bSuccess && numFilesToPost ) {
  749.         // One extra for trailing NULL.
  750.         char **filesToPost = (char **)XP_ALLOC((numFilesToPost + 1) * sizeof(char*));
  751.         if ( !filesToPost ) {
  752.             XP_ASSERT(0);
  753.             return;
  754.         }
  755.  
  756.         // Where to put the files on the server.
  757.         // FTP publish will ignore the path info in postTo and will just use 
  758.         // the filename after the last slash.
  759.         char **postTo = NULL; 
  760.         postTo = (char **)XP_ALLOC((numFilesToPost + 1) * sizeof(char*));
  761.         if ( !postTo ) {
  762.             XP_ASSERT(0);
  763.             XP_FREE(filesToPost);
  764.             return;
  765.         }
  766.  
  767.         // Not NULL-terminated.
  768.         XP_Bool *addCRLF = (XP_Bool *)XP_ALLOC((numFilesToPost) * sizeof(XP_Bool));
  769.         if (!addCRLF) {
  770.             XP_ASSERT(0);
  771.             XP_FREE(filesToPost);
  772.             XP_FREE(postTo);
  773.             return;
  774.         }
  775.  
  776.         // Copying filenames, reversing order or list and removing blanks at
  777.         // the same time.
  778.         int n,m;        
  779.         for ( n = 0, m = numFilesToPost - 1; 
  780.               n < m_tempFilenames.Size(); n++ ) {
  781.             // Insert into list backwards, because NET_PublishFilesTo publishes in reverse order.
  782.             // So, HTML file will be published first.
  783.             if (m_tempFilenames[n]) {
  784.               filesToPost[m] = XP_STRDUP(m_tempFilenames[n]);
  785.               postTo[m] = XP_STRDUP(m_remoteURLs[n]);
  786.  
  787.               // Only first file is treated as text, rest are whatever netlib decides.
  788.           // well actually only if it's not a pre-encrypted file!
  789.               addCRLF[m] = (n == 0) && !IsFirstBinary(); 
  790.               m--;
  791.             }
  792.         }        
  793.         // Otherwise we counted numFilesToPost wrong.
  794.         XP_ASSERT(m == -1);
  795.  
  796.          // Trailing NULL.
  797.         filesToPost[numFilesToPost] = NULL;
  798.         postTo[numFilesToPost] = NULL;
  799.  
  800.  
  801.  
  802.         // Temporarily remove characters after final slash
  803.         // from m_pRemoteURL, so pRemoteFullURL is a directory.
  804.         char *lastSlash = XP_STRRCHR(m_pRemoteURL,'/');
  805.         char saved;
  806.         if (lastSlash) {
  807.           saved = *(lastSlash + 1);
  808.           *(lastSlash + 1) = '\0';
  809.         }
  810.  
  811.         char *pRemoteFullURL = NULL;
  812.         if (!NET_MakeUploadURL(&pRemoteFullURL,m_pRemoteURL,m_pUsername,m_pPassword)) {
  813.           pRemoteFullURL = NULL; // Just to be sure.
  814.         }
  815.  
  816.         // Restore m_pRemoteURL.
  817.         *(lastSlash + 1) = saved;
  818.  
  819.         if (!pRemoteFullURL) {
  820.           return;
  821.         }
  822.  
  823.         if (m_bIsHTTP) {
  824.           // m_pRemoteURL may or may not be a directory.
  825.           // username and password are passed in separately, not through the
  826.           // URL, to avoid ever being displayed on screen to the user.
  827.           NET_PublishFilesTo(m_pMWContext, filesToPost, postTo, addCRLF,
  828.                              m_pRemoteURL,m_pUsername,m_pPassword,
  829.                              edt_CTapeFSExit, (void *)this);
  830.         }
  831.         else {  
  832.           // pRemoteFullURL must be a directory for FTP publishing.
  833.           // pRemoteFullURL contains username/password information, maybe we 
  834.           // should modify ns/lib/libnet/mkftp.c to deal with username/password
  835.           // in the URL struct like mkhttp.c does.
  836.           NET_PublishFilesTo(m_pMWContext, filesToPost, postTo, addCRLF,
  837.                             pRemoteFullURL,NULL,NULL,
  838.                             edt_CTapeFSExit, (void *)this);
  839.         }
  840.         // edt_CTapeFSExit will call pfComplete() and delete this.
  841.  
  842.         XP_FREEIF(pRemoteFullURL);
  843.     }
  844.     else {
  845.       if (m_pfComplete) {
  846.         // Pass in TRUE because CTapeFSComplete() did the right thing, even 
  847.         // though there may have been errors earlier on.
  848.         m_pfComplete(TRUE,m_pArg);
  849.       }
  850.       delete this;
  851.     }
  852. }
  853.  
  854. char *CTapeFSPublish::makeLocal(char *baseURL,char *srcURL) {
  855.     // Return value.
  856.     char *ret = NULL;  
  857.     
  858.     // Set ret to be directory to place files in.
  859.     int len = XP_STRLEN(baseURL);
  860.     if (len < 1) {
  861.         XP_ASSERT(0);
  862.         return NULL;
  863.     }
  864.  
  865.     if (baseURL[len-1] == '/') {
  866.         // baseURL is already a directory.
  867.         ret = XP_STRDUP(baseURL);
  868.     }
  869.     else {
  870.         char *trail = XP_STRRCHR(baseURL,'/');
  871.         if (trail == NULL) {
  872.             XP_ASSERT(0);
  873.             return NULL;
  874.         }
  875.         // Temporarily set the char after the last slash to NULL and copy everything before and 
  876.         // including the last slash.  We know the '/' is not the last character, since we checked for that 
  877.         // above.
  878.         char tmp = *(trail + 1);
  879.         *(trail + 1) = '\0';
  880.         ret = XP_STRDUP(baseURL);        
  881.         *(trail + 1) = tmp;
  882.     }    
  883.  
  884.     char *localName = FE_URLToLocalName(srcURL);
  885.     if (localName == NULL) {
  886.         XP_ASSERT(0);
  887.         return NULL;
  888.     }
  889.  
  890.     if (!ret) {
  891.         XP_ASSERT(0);
  892.         return NULL;
  893.     }
  894.  
  895.     ret = XP_AppendStr(ret,localName);
  896.     XP_ASSERT(ret); 
  897.     XP_FREE(localName);
  898.  
  899.     return ret;
  900. }
  901.  
  902. #endif // EDITOR
  903.