1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
11 * Copyright (C) 2005 Christi Alice Scarborough
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
22 #include "installlog.h"
25 // This class allows us to return directories as well as files to
27 class wxDirTraverserIncludeDirs
: public wxDirTraverser
30 wxDirTraverserIncludeDirs(wxArrayString
& files
) : m_files(files
) { }
32 virtual wxDirTraverseResult
OnFile(const wxString
& filename
)
34 m_files
.Add(filename
);
35 return wxDIR_CONTINUE
;
38 virtual wxDirTraverseResult
OnDir(const wxString
& dirname
)
41 return wxDIR_CONTINUE
;
45 wxArrayString
& m_files
;
48 wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry
);
50 const wxChar
* _rootmatch
[] = {
55 wxT("battery_bench.txt"),
58 const wxArrayString
* rootmatch
= new wxArrayString(
59 (size_t) (sizeof(_rootmatch
) / sizeof(wxChar
*)), _rootmatch
);
61 bool InstallTheme(wxString Themesrc
)
63 wxString dest
,src
,err
;
65 int pos
= Themesrc
.Find('/',true);
66 wxString themename
= Themesrc
.SubString(pos
+1,Themesrc
.Length());
68 src
.Printf(wxT("%s/%s"), gv
->themes_url
.c_str(),Themesrc
.c_str());
69 dest
.Printf(wxT("%s" PATH_SEP
"download" PATH_SEP
"%s"),
70 gv
->stdpaths
->GetUserDataDir().c_str(),themename
.c_str());
71 if( DownloadURL(src
, dest
) )
74 err
.Printf(wxT("Unable to download %s"), src
.c_str() );
75 ERR_DIALOG(err
, wxT("Install Theme"));
81 err
.Printf(wxT("The Zip %s does not contain the correct dir structure"), dest
.c_str());
82 ERR_DIALOG(err
, wxT("Install Theme"));
86 if(UnzipFile(dest
,gv
->curdestdir
, true))
88 err
.Printf(wxT("Unable to unzip %s to %s"), dest
.c_str(), gv
->curdestdir
.c_str());
89 ERR_DIALOG(err
, wxT("Install Theme"));
96 bool checkZip(wxString zipname
)
100 wxFFileInputStream
* in_file
= new wxFFileInputStream(zipname
);
101 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
103 entry
.reset(in_zip
->GetNextEntry());
105 wxString name
= entry
->GetName();
108 if(name
.Contains(wxT(".rockbox")))
116 int DownloadURL(wxString src
, wxString dest
)
118 int input
, errnum
= 0, success
= false;
119 wxString buf
, errstr
;
120 wxLogVerbose(wxT("=== begin DownloadURL(%s,%s)"), src
.c_str(),
123 buf
.Printf(wxT("Fetching %s"), src
.c_str());
124 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Downloading"),
125 buf
, 100, NULL
, wxPD_APP_MODAL
|
126 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
127 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
129 progress
->SetSize(500,200);
132 wxURL
* in_http
= new wxURL(src
);
133 if (in_http
->GetError() == wxURL_NOERR
)
136 wxFFileOutputStream
* os
= new wxFFileOutputStream(dest
);
140 wxInputStream
* is
= in_http
->GetInputStream();
144 size_t filesize
= is
->GetSize();
148 char buffer
[FILE_BUFFER_SIZE
+ 1];
153 is
->Read(buffer
, FILE_BUFFER_SIZE
);
157 os
->Write(buffer
, is
->LastRead());
161 current
+= os
->LastWrite();
162 if (!progress
->Update(current
* 100 / filesize
))
164 errstr
= wxT("Download aborted by user");
171 errnum
= os
->GetLastError();
172 errstr
.Printf(wxT("Can't write to output stream (%s)"),
173 stream_err_str(errnum
).c_str() );
180 errnum
= is
->GetLastError();
181 if (errnum
== wxSTREAM_EOF
)
186 errstr
.Printf(wxT("Can't read from input stream (%s)"),
187 stream_err_str(errnum
).c_str() );
194 errnum
= os
->GetLastError();
195 errstr
.Printf(wxT("Can't close output file (%s)"),
196 stream_err_str(errnum
).c_str() );
201 if (! errnum
) success
= true;
205 errnum
= is
->GetLastError();
206 errstr
.Printf(wxT("Can't get input stream size (%s)"),
207 stream_err_str(errnum
).c_str() );
212 errnum
= in_http
->GetError();
213 errstr
.Printf(wxT("Can't get input stream (%d)"), errnum
);
218 errnum
= os
->GetLastError();
219 errstr
.Printf(wxT("Can't create output stream (%s)"),
220 stream_err_str(errnum
).c_str() );
225 errstr
.Printf(wxT("Can't open URL %s (%d)"), src
.c_str(),
226 in_http
->GetError() );
235 if (errnum
== 0) errnum
= 999;
238 buf
.Printf(wxT("%s reading\n%s"),
239 errstr
.c_str(), src
.c_str());
240 ERR_DIALOG(buf
, wxT("Download URL"));
243 buf
.Printf(wxT("%s writing to download\n/%s"),
244 errstr
.c_str(), dest
.c_str());
245 ERR_DIALOG(buf
, wxT("Download URL"));
250 wxLogVerbose(wxT("=== end DownloadURL"));
254 int UnzipFile(wxString src
, wxString destdir
, bool isInstall
)
257 wxString in_str
, progress_msg
, buf
;
258 int errnum
= 0, curfile
= 0, totalfiles
= 0;
259 InstallLog
* log
= NULL
;
261 wxLogVerbose(wxT("===begin UnzipFile(%s,%s,%i)"),
262 src
.c_str(), destdir
.c_str(), isInstall
);
264 wxFFileInputStream
* in_file
= new wxFFileInputStream(src
);
265 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
268 if (! in_zip
->IsOk() )
270 errnum
= in_zip
->GetLastError();
271 buf
.Printf(wxT("Can't open ZIP stream %s for reading (%s)"),
272 src
.c_str(), stream_err_str(errnum
).c_str() );
273 ERR_DIALOG(buf
, wxT("Unzip File") );
279 totalfiles
= in_zip
->GetTotalEntries();
280 if (! in_zip
->IsOk() )
282 errnum
= in_zip
->GetLastError();
283 buf
.Printf(wxT("Error Getting total ZIP entries for %s (%s)"),
284 src
.c_str(), stream_err_str(errnum
).c_str() );
285 ERR_DIALOG(buf
, wxT("Unzip File") );
292 errnum
= in_file
->GetLastError();
293 buf
.Printf(wxT("Can't open %s (%s)"), src
.c_str(),
294 stream_err_str(errnum
).c_str() );
295 ERR_DIALOG(buf
, wxT("Unzip File") );
301 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Unpacking archive"),
302 wxT("Preparing to unpack the downloaded files to your audio"
303 "device"), totalfiles
, NULL
, wxPD_APP_MODAL
|
304 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
305 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
308 // We're not overly worried if the logging fails
311 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), destdir
.c_str());
312 log
= new InstallLog(buf
);
316 (entry
.reset(in_zip
->GetNextEntry()), entry
.get() != NULL
) )
320 wxString name
= entry
->GetName();
321 progress_msg
.Printf(wxT("Unpacking %s"), name
.c_str());
322 if (! progress
->Update(curfile
, progress_msg
) ) {
323 buf
.Printf(wxT("Unpacking cancelled by user"));
329 in_str
.Printf(wxT("%s" PATH_SEP
"%s"), destdir
.c_str(), name
.c_str());
331 if (entry
->IsDir() ) {
332 if (!wxDirExists(in_str
) ) {
333 if (! wxMkdir(in_str
, 0777) ) {
334 buf
.Printf(wxT("Unable to create directory %s"),
340 log
->WriteFile(name
, true); // Directory
344 wxFFileOutputStream
* out
= new wxFFileOutputStream(in_str
);
347 buf
.Printf(wxT("Can't open file %s for writing"), in_str
.c_str() );
350 } else if (isInstall
)
352 log
->WriteFile(name
);
357 buf
.Printf(wxT("Can't write to %s (%d)"), in_str
.c_str(),
358 errnum
= out
->GetLastError() );
361 if (!in_zip
->IsOk() && ! in_file
->GetLastError() == wxSTREAM_EOF
)
363 buf
.Printf(wxT("Can't read from %s (%d)"), src
.c_str(),
364 errnum
= in_file
->GetLastError() );
367 if (! out
->Close() && errnum
== 0)
369 buf
.Printf(wxT("Unable to close %s (%d)"), in_str
.c_str(),
370 errnum
= out
->GetLastError() );
378 delete in_zip
; delete in_file
; delete progress
;
382 ERR_DIALOG(buf
, wxT("Unzip File"));
386 wxLogVerbose(wxT("=== end UnzipFile"));
390 int Uninstall(const wxString dir
, bool isFullUninstall
) {
391 wxString buf
, uninst
;
393 bool errflag
= false;
394 InstallLog
*log
= NULL
;
395 wxArrayString
* FilesToRemove
= NULL
;
397 wxLogVerbose(wxT("=== begin Uninstall(%s,%i)"), dir
.c_str(), isFullUninstall
);
399 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Uninstalling"),
400 wxT("Reading uninstall data from jukebox"), 100, NULL
,
401 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
402 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
405 if (! isFullUninstall
)
408 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dir
.c_str());
409 log
= new InstallLog(buf
, false); // Don't create the log
410 FilesToRemove
= log
->GetInstalledFiles();
413 if (FilesToRemove
== NULL
|| FilesToRemove
->GetCount() < 1) {
415 if ( wxMessageDialog(NULL
,
416 wxT("Rockbox Utility can't find any uninstall data on this "
418 "Would you like to attempt a full uninstall?\n"
419 "(WARNING: A full uninstall removes all files in your Rockbox "
421 wxT("Standard uninstall not possible"),
422 wxICON_EXCLAMATION
| wxYES_NO
| wxNO_DEFAULT
).ShowModal()
425 isFullUninstall
= true;
428 MESG_DIALOG(wxT("Uninstall cancelled by user"));
435 if (isFullUninstall
)
437 buf
.Printf(wxT("%s" PATH_SEP
".rockbox"), dir
.c_str());
440 WARN_DIALOG(wxT("Unable to completely remove Rockbox directory"),
441 wxT("Full uninstall") );
445 wxDir
* root
= new wxDir(dir
);
446 wxArrayString
* special
= new wxArrayString();
447 // Search for files for deletion in the jukebox root
448 for (i
= 0; i
< rootmatch
->GetCount(); i
++)
450 const wxString match
= (*rootmatch
)[i
];
451 root
->GetAllFiles(dir
, special
, match
, wxDIR_FILES
);
455 // Sort in reverse order so we get directories last
458 for (i
= 0; i
< special
->GetCount(); i
++)
461 if (wxDirExists((*special
)[i
]) )
463 // We don't check the return code since we don't want non
464 // empty dirs disappearing.
465 wxRmdir((*special
)[i
]);
467 } else if (wxFileExists((*special
)[i
]) )
469 if (! wxRemoveFile((*special
)[i
]) )
471 buf
.Printf(wxT("Can't delete %s"), (*special
)[i
].c_str());
472 WARN_DIALOG(buf
.c_str(), wxT("Full uninstall"));
476 // Otherwise there isn't anything there, so we don't have to worry.
481 wxString instplat
, this_path_sep
;
482 unsigned int totalfiles
, rc
;
483 totalfiles
= FilesToRemove
->GetCount();
484 FilesToRemove
->Sort(true); // Reverse alphabetical ie dirs after files
486 for (i
= 0; i
< totalfiles
; i
++)
488 // If we're running on the device, let's not delete our own
491 FilesToRemove
->Item(i
).StartsWith(PATH_SEP
492 wxT("RockboxUtility")) )
497 wxString
* buf2
= new wxString
;
498 buf
.Printf(wxT("%s%s"), dir
.c_str() , FilesToRemove
->Item(i
).c_str() );
499 buf2
->Format(wxT("Deleting %s"), buf
.c_str());
501 if (! progress
->Update((i
+ 1) * 100 / totalfiles
, *buf2
) )
503 WARN_DIALOG(wxT("Cancelled by user"), wxT("Normal Uninstall"));
508 if (wxDirExists(buf
) )
510 // If we're about to attempt to remove .rockbox. delete
511 // install data first
512 buf2
->Printf(wxT("%s" PATH_SEP
".rockbox"), dir
.c_str() );
513 if ( buf
.IsSameAs(buf2
->c_str()) )
515 buf2
->Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dir
.c_str());
519 if ( (rc
= ! wxRmdir(buf
)) )
521 buf
= buf
.Format(wxT("Can't remove directory %s"),
524 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
526 } else if (wxFileExists(buf
) )
528 if ( (rc
= ! wxRemoveFile(buf
)) )
530 buf
= buf
.Format(wxT("Can't delete file %s"),
533 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
538 buf
= buf
.Format(wxT("Can't find file or directory %s"),
540 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall") );
543 uninst
= uninst
.AfterFirst('\n');
547 ERR_DIALOG(wxT("Unable to remove some files"),
548 wxT("Standard uninstall")) ;
551 if (FilesToRemove
!= NULL
) delete FilesToRemove
;
555 wxLogVerbose(wxT("=== end Uninstall"));
560 wxString
stream_err_str(int errnum
)
565 case wxSTREAM_NO_ERROR
:
566 out
= wxT("wxSTREAM_NO_ERROR");
569 out
= wxT("wxSTREAM_EOF");
571 case wxSTREAM_WRITE_ERROR
:
572 out
= wxT("wxSTREAM_WRITE_ERROR");
574 case wxSTREAM_READ_ERROR
:
575 out
= wxT("wxSTREAM_READ_ERROR");
578 out
= wxT("UNKNOWN");
584 bool InstallRbutil(wxString dest
)
586 wxArrayString filestocopy
;
587 wxString str
, buf
, dstr
, localpath
, destdir
;
590 bool copied_exe
= false, made_rbdir
= false;
593 buf
.Printf(wxT("%s" PATH_SEP
".rockbox"), dest
.c_str() );
595 if (! wxDirExists(buf
) )
601 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dest
.c_str() );
602 log
= new InstallLog(buf
);
603 if (made_rbdir
) log
->WriteFile(wxT(".rockbox"), true);
605 destdir
.Printf(wxT("%s" PATH_SEP
"RockboxUtility"), dest
.c_str());
606 if (! wxDirExists(destdir
) )
608 if (! wxMkdir(destdir
, 0777) )
610 buf
.Printf(wxT("%s (%s)"),
611 wxT("Unable to create directory for installer"), destdir
.c_str());
612 WARN_DIALOG(buf
, wxT("Portable install") );
615 log
->WriteFile(wxT("RockboxUtility"), true);
618 dir
.GetAllFiles(gv
->ResourceDir
, &filestocopy
, wxT("*"),
620 if (filestocopy
.GetCount() < 1)
622 WARN_DIALOG(wxT("No files to copy"), wxT("Portable install") );
626 // Copy the contents of the program directory
627 for (i
= 0; i
< filestocopy
.GetCount(); i
++)
629 if (filestocopy
[i
].AfterLast(PATH_SEP_CHR
) == EXE_NAME
)
634 dstr
.Printf(wxT("%s" PATH_SEP
"%s"), destdir
.c_str(),
635 filestocopy
[i
].AfterLast(PATH_SEP_CHR
).c_str());
636 if (! wxCopyFile(filestocopy
[i
], dstr
) )
638 buf
.Printf(wxT("%s (%s -> %s)"),
639 wxT("Error copying file"), filestocopy
[i
].c_str(), dstr
.c_str());
640 WARN_DIALOG(buf
, wxT("Portable Install") );
644 buf
.Replace(dest
, wxEmptyString
, false);
650 str
.Printf(wxT("%s" PATH_SEP EXE_NAME
), gv
->AppDir
.c_str());
651 dstr
.Printf(wxT("%s" PATH_SEP EXE_NAME
), destdir
.c_str());
652 if (! wxCopyFile(str
, dstr
) )
654 buf
.Printf(wxT("Can't copy program binary %s -> %s"),
655 str
.c_str(), dstr
.c_str() );
656 WARN_DIALOG(buf
, wxT("Portable Install") );
660 buf
.Replace(dest
, wxEmptyString
, false);
664 // Copy the local ini file so that it knows that it's a portable copy
665 gv
->UserConfig
->Flush();
666 dstr
.Printf(wxT("%s" PATH_SEP
"RockboxUtility.cfg"), destdir
.c_str());
667 if (! wxCopyFile(gv
->UserConfigFile
, dstr
) )
669 buf
.Printf(wxT("%s (%s -> %s)"),
670 wxT("Unable to install user config file"), gv
->UserConfigFile
.c_str(),
672 WARN_DIALOG(buf
, wxT("Portable Install") );
676 buf
.Replace(dest
, wxEmptyString
, false);
683 bool rm_rf(wxString file
)
685 wxLogVerbose(wxT("=== begin rm-rf(%s)"), file
.c_str() );
688 wxArrayString selected
;
689 wxDirTraverserIncludeDirs
wxdtid(selected
);
690 unsigned int rc
= 0, i
;
691 bool errflag
= false;
693 if (wxFileExists(file
) )
695 rc
= ! wxRemoveFile(file
);
696 } else if (wxDirExists(file
) )
698 wxDir
* dir
= new wxDir(file
);;
699 dir
->Traverse(wxdtid
);
701 // Sort into reverse alphabetical order for deletion in correct order
702 // (directories after files)
706 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Removing files"),
707 wxT("Deleting files"), selected
.GetCount(), NULL
,
708 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
709 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
711 for (i
= 0; i
< selected
.GetCount(); i
++)
713 wxLogVerbose(selected
[i
]);
714 if (progress
!= NULL
)
716 buf
.Printf(wxT("Deleting %s"), selected
[i
].c_str() );
717 if (! progress
->Update(i
, buf
))
719 WARN_DIALOG(wxT("Cancelled by user"), wxT("Erase Files"));
725 if (wxDirExists(selected
[i
]) )
727 if ((rc
= ! wxRmdir(selected
[i
])) )
729 buf
.Printf(wxT("Can't remove directory %s"),
730 selected
[i
].c_str());
732 WARN_DIALOG(buf
.c_str(), wxT("Erase files"));
734 } else if ((rc
= ! wxRemoveFile(selected
[i
])) )
736 buf
.Printf(wxT("Error deleting file %s"), selected
[i
].c_str() );
738 WARN_DIALOG(buf
.c_str(),wxT("Erase files"));
744 buf
.Printf(wxT("Can't find expected file %s"), file
.c_str());
745 WARN_DIALOG(buf
.c_str(), wxT("Erase files"));
749 wxLogVerbose(wxT("=== end rm-rf"));
750 return rc
? true : false;