Back to index

lightning-sunbird  0.9+nobinonly
Copy.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Roaming code.
00016  *
00017  * The Initial Developer of the Original Code is 
00018  *   Ben Bucksch <http://www.bucksch.org> of
00019  *   Beonex <http://www.beonex.com>
00020  * Portions created by the Initial Developer are Copyright (C) 2002-2004
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "Copy.h"
00040 #include "nsIComponentManager.h"
00041 #include "nsILocalFile.h"
00042 #include "nsXPIDLString.h"
00043 
00044 #define kRegTreeCopy (NS_LITERAL_STRING("Copy"))
00045 #define kRegKeyRemote (NS_LITERAL_STRING("RemoteDir"))
00046 
00047 // Internal helper functions unrelated to class
00048 
00049 /* @param fileSubPath  works for subpaths or just filenames?
00050                        doesn't really matter for us. */
00051 static nsresult CopyFile(nsCOMPtr<nsIFile> fromDir,
00052                          nsCOMPtr<nsIFile> toDir,
00053                          nsAString& fileSubPath)
00054 {
00055   nsresult rv;
00056 
00057   nsCOMPtr<nsIFile> fromFile;
00058   rv = fromDir->Clone(getter_AddRefs(fromFile));
00059   NS_ENSURE_SUCCESS(rv, rv);
00060 
00061   rv = fromFile->Append(fileSubPath);
00062   NS_ENSURE_SUCCESS(rv, rv);
00063 
00064   nsCOMPtr<nsIFile> toFileOld;
00065   rv = toDir->Clone(getter_AddRefs(toFileOld));
00066   NS_ENSURE_SUCCESS(rv, rv);
00067 
00068   rv = toFileOld->Append(fileSubPath);
00069   NS_ENSURE_SUCCESS(rv, rv);
00070 
00071   PRBool exists;
00072   rv = fromFile->Exists(&exists);
00073   NS_ENSURE_SUCCESS(rv, rv);
00074 
00075   if (exists)
00076   {
00077     rv = toFileOld->Remove(PR_FALSE);
00078     rv = fromFile->CopyTo(toDir, fileSubPath);
00079   }
00080   else
00081   {
00082     rv = NS_ERROR_FILE_NOT_FOUND;
00083   }
00084   return rv;
00085 }
00086 
00087 static void AppendElementsToStrArray(nsCStringArray& target, nsCStringArray& source)
00088 {
00089   for (PRInt32 i = source.Count() - 1; i >= 0; i--)
00090     target.AppendCString(*source.CStringAt(i));
00091 }
00092 
00093 /*
00094  * nsSRoamingProtocol implementation
00095  */
00096 
00097 nsresult Copy::Init(Core* aController)
00098 {
00099   nsresult rv;
00100   mController = aController;
00101   if (!mController)
00102     return NS_ERROR_INVALID_ARG;
00103 
00104   // Get prefs
00105   nsCOMPtr<nsIRegistry> registry;
00106   rv = mController->GetRegistry(registry);
00107   NS_ENSURE_SUCCESS(rv, rv);
00108 
00109   nsRegistryKey regkey;
00110   rv = mController->GetRegistryTree(regkey);
00111   NS_ENSURE_SUCCESS(rv, rv);
00112 
00113   rv = registry->GetKey(regkey,
00114                         kRegTreeCopy.get(),
00115                         &regkey);
00116   NS_ENSURE_SUCCESS(rv, rv);
00117 
00118   nsXPIDLString remoteDirPref;
00119   rv = registry->GetString(regkey, kRegKeyRemote.get(),
00120                            getter_Copies(remoteDirPref));
00121   NS_ENSURE_SUCCESS(rv, rv);
00122 
00123   nsCOMPtr<nsILocalFile> lf;
00124   rv = NS_NewLocalFile(remoteDirPref, PR_FALSE,
00125                        getter_AddRefs(lf));
00126   NS_ENSURE_SUCCESS(rv, rv);
00127   
00128   mRemoteDir = lf;
00129 
00130   rv = mController->GetProfileDir(getter_AddRefs(mProfileDir));
00131   NS_ENSURE_SUCCESS(rv, rv);
00132 
00133   if (!mProfileDir)
00134     return NS_ERROR_FILE_NOT_FOUND;
00135 
00136   return NS_OK;
00137 }
00138 
00139 nsresult Copy::Download()
00140 {
00141   return DownUpLoad(PR_TRUE);
00142 }
00143 
00144 nsresult Copy::Upload()
00145 {
00146   return DownUpLoad(PR_FALSE);
00147 }
00148 
00149 nsresult Copy::DownUpLoad(PRBool download)
00150 {
00151   nsresult rv = NS_OK;
00152 
00153   const nsCStringArray* files = mController->GetFilesToRoam();
00154 
00155   // Check for conflicts
00156   nsCStringArray conflicts(10);
00157   nsCStringArray copyfiles(10);
00158   PRInt32 i;
00159   for (i = files->Count() - 1; i >= 0; i--)
00160   {
00161     nsCString& file = *files->CStringAt(i);
00162     NS_ConvertASCIItoUTF16 fileL(file);
00163 
00164     nsCOMPtr<nsIFile> profileFile;
00165     rv = mProfileDir->Clone(getter_AddRefs(profileFile));
00166     NS_ENSURE_SUCCESS(rv, rv);
00167 
00168     rv = profileFile->Append(fileL);
00169     NS_ENSURE_SUCCESS(rv, rv);
00170 
00171     nsCOMPtr<nsIFile> remoteFile;
00172     rv = mRemoteDir->Clone(getter_AddRefs(remoteFile));
00173     NS_ENSURE_SUCCESS(rv, rv);
00174 
00175     rv = remoteFile->Append(fileL);
00176     NS_ENSURE_SUCCESS(rv, rv);
00177 
00178     // avoid conflicts for missing files
00179     PRBool remoteExists = PR_TRUE;
00180     PRBool profileExists = PR_TRUE;
00181     remoteFile->Exists(&remoteExists);
00182     profileFile->Exists(&profileExists);
00183     if (download)
00184     {
00185       if (!remoteExists)
00186         continue;
00187 
00188       if (!profileExists) {
00189         copyfiles.AppendCString(file);
00190         continue;
00191         /* actually, this code is not needed given how the last modified
00192            code below works, but for readability and just in case... */
00193       }
00194     }
00195     else
00196     {
00197       if (!profileExists)
00198         continue;
00199 
00200       if (!remoteExists) {
00201         copyfiles.AppendCString(file);
00202         continue;
00203       }
00204     }
00205 
00206     PRInt64 profileTime = 0;
00207     PRInt64 remoteTime = 0;
00208     profileFile->GetLastModifiedTime(&profileTime);
00209     remoteFile->GetLastModifiedTime(&remoteTime);
00210 
00211     // do we have a conflict?
00212     if (download
00213         ? profileTime > remoteTime
00214         : profileTime < remoteTime )
00215       conflicts.AppendCString(file);
00216     else
00217       copyfiles.AppendCString(file);
00218   }
00219 
00220   // Ask user about conflicts
00221   nsCStringArray copyfiles_conflicts(10);
00222   rv = mController->ConflictResolveUI(download, conflicts,
00223                                       &copyfiles_conflicts);
00224   NS_ENSURE_SUCCESS(rv, rv);
00225 
00226   AppendElementsToStrArray(copyfiles, copyfiles_conflicts);
00227 
00228   // Copy
00229   for (i = copyfiles.Count() - 1; i >= 0; i--)
00230   {
00231     const nsCString& file = *copyfiles.CStringAt(i);
00232     NS_ConvertASCIItoUTF16 fileL(file);
00233     if (download)
00234       rv = CopyFile(mRemoteDir, mProfileDir, fileL);
00235     else
00236       rv = CopyFile(mProfileDir, mRemoteDir, fileL);
00237   }
00238 
00239   return rv;
00240 }