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 int DownloadURL(wxString src
, wxString dest
)
63 int input
, errnum
= 0, success
= false;
65 wxLogVerbose(_("=== begin DownloadURL(%s,%s)"), src
.c_str(),
68 buf
.Printf(_("Fetching %s"), src
.c_str());
69 wxProgressDialog
* progress
= new wxProgressDialog(_("Downloading"),
70 buf
, 100, NULL
, wxPD_APP_MODAL
|
71 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
72 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
76 wxURL
* in_http
= new wxURL(src
);
77 if (in_http
->GetError() == wxURL_NOERR
)
80 wxFFileOutputStream
* os
= new wxFFileOutputStream(dest
);
84 wxInputStream
* is
= in_http
->GetInputStream();
88 size_t filesize
= is
->GetSize();
92 char buffer
[FILE_BUFFER_SIZE
+ 1];
97 is
->Read(buffer
, FILE_BUFFER_SIZE
);
101 os
->Write(buffer
, is
->LastRead());
105 current
+= os
->LastWrite();
106 if (!progress
->Update(current
* 100 / filesize
))
108 errstr
= _("Download aborted by user");
115 errnum
= os
->GetLastError();
116 errstr
.Printf(_("Can't write to output stream (%s)"),
117 stream_err_str(errnum
).c_str() );
124 errnum
= is
->GetLastError();
125 if (errnum
== wxSTREAM_EOF
)
130 errstr
.Printf(_("Can't read from input stream (%s)"),
131 stream_err_str(errnum
).c_str() );
138 errnum
= os
->GetLastError();
139 errstr
.Printf(_("Can't close output file (%s)"),
140 stream_err_str(errnum
).c_str() );
145 if (! errnum
) success
= true;
149 errnum
= is
->GetLastError();
150 errstr
.Printf(_("Can't get input stream size (%s)"),
151 stream_err_str(errnum
).c_str() );
156 errnum
= in_http
->GetError();
157 errstr
.Printf(_("Can't get input stream (%d)"), errnum
);
162 errnum
= os
->GetLastError();
163 errstr
.Printf(_("Can't create output stream (%s)"),
164 stream_err_str(errnum
).c_str() );
169 errstr
.Printf(_("Can't open URL %s (%d)"), src
.c_str(),
170 in_http
->GetError() );
179 if (errnum
== 0) errnum
= 999;
182 buf
.Printf(_("%s reading\n%s"),
183 errstr
.c_str(), src
.c_str());
184 ERR_DIALOG(buf
, _("Download URL"));
187 buf
.Printf(_("%s writing to download\n/%s"),
188 errstr
.c_str(), dest
.c_str());
189 ERR_DIALOG(buf
, _("Download URL"));
194 wxLogVerbose(_("=== end DownloadURL"));
198 int UnzipFile(wxString src
, wxString destdir
, bool isInstall
)
201 wxString in_str
, progress_msg
, buf
;
202 int errnum
= 0, curfile
= 0, totalfiles
= 0;
203 InstallLog
* log
= NULL
;
205 wxLogVerbose(_("===begin UnzipFile(%s,%s,%i)"),
206 src
.c_str(), destdir
.c_str(), isInstall
);
208 wxFFileInputStream
* in_file
= new wxFFileInputStream(src
);
209 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
212 if (! in_zip
->IsOk() )
214 errnum
= in_zip
->GetLastError();
215 buf
.Printf(_("Can't open ZIP stream %s for reading (%s)"),
216 src
.c_str(), stream_err_str(errnum
).c_str() );
217 ERR_DIALOG(buf
, _("Unzip File") );
223 totalfiles
= in_zip
->GetTotalEntries();
224 if (! in_zip
->IsOk() )
226 errnum
= in_zip
->GetLastError();
227 buf
.Printf(_("Error Getting total ZIP entries for %s (%s)"),
228 src
.c_str(), stream_err_str(errnum
).c_str() );
229 ERR_DIALOG(buf
, _("Unzip File") );
236 errnum
= in_file
->GetLastError();
237 buf
.Printf(_("Can't open %s (%s)"), src
.c_str(),
238 stream_err_str(errnum
).c_str() );
239 ERR_DIALOG(buf
, _("Unzip File") );
245 wxProgressDialog
* progress
= new wxProgressDialog(_("Unpacking archive"),
246 _("Preparing to unpack the downloaded files to your audio"
247 "device"), totalfiles
, NULL
, wxPD_APP_MODAL
|
248 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
249 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
252 // We're not overly worried if the logging fails
255 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), destdir
.c_str());
256 log
= new InstallLog(buf
);
260 (entry
.reset(in_zip
->GetNextEntry()), entry
.get() != NULL
) )
264 wxString name
= entry
->GetName();
265 progress_msg
.Printf(_("Unpacking %s"), name
.c_str());
266 if (! progress
->Update(curfile
, progress_msg
) ) {
267 buf
.Printf(_("Unpacking cancelled by user"));
273 in_str
.Printf(wxT("%s" PATH_SEP
"%s"), destdir
.c_str(), name
.c_str());
275 if (entry
->IsDir() ) {
276 if (!wxDirExists(in_str
) ) {
277 if (! wxMkdir(in_str
, 0777) ) {
278 buf
.Printf(_("Unable to create directory %s"),
284 log
->WriteFile(name
, true); // Directory
288 wxFFileOutputStream
* out
= new wxFFileOutputStream(in_str
);
291 buf
.Printf(_("Can't open file %s for writing"), in_str
.c_str() );
294 } else if (isInstall
)
296 log
->WriteFile(name
);
301 buf
.Printf(_("Can't write to %s (%d)"), in_str
.c_str(),
302 errnum
= out
->GetLastError() );
305 if (!in_zip
->IsOk() && ! in_file
->GetLastError() == wxSTREAM_EOF
)
307 buf
.Printf(_("Can't read from %s (%d)"), src
.c_str(),
308 errnum
= in_file
->GetLastError() );
311 if (! out
->Close() && errnum
== 0)
313 buf
.Printf(_("Unable to close %s (%d)"), in_str
.c_str(),
314 errnum
= out
->GetLastError() );
322 delete in_zip
; delete in_file
; delete progress
;
326 ERR_DIALOG(buf
, _("Unzip File"));
330 wxLogVerbose(_("=== end UnzipFile"));
334 int Uninstall(const wxString dir
, bool isFullUninstall
) {
335 wxString buf
, uninst
;
336 bool gooddata
= false;
338 bool errflag
= false;
339 InstallLog
*log
= NULL
;
340 wxArrayString
* FilesToRemove
= NULL
;
342 wxLogVerbose(_("=== begin Uninstall(%s,%i)"), dir
.c_str(), isFullUninstall
);
344 wxProgressDialog
* progress
= new wxProgressDialog(_("Uninstalling"),
345 _("Reading uninstall data from jukebox"), 100, NULL
,
346 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
347 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
350 if (! isFullUninstall
)
353 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dir
.c_str());
354 log
= new InstallLog(buf
, false); // Don't create the log
355 FilesToRemove
= log
->GetInstalledFiles();
358 if (FilesToRemove
== NULL
|| FilesToRemove
->GetCount() < 1) {
360 if ( wxMessageDialog(NULL
,
361 _("Rockbox Utility can't find any uninstall data on this "
363 "Would you like to attempt a full uninstall?\n"
364 "(WARNING: A full uninstall removes all files in your Rockbox "
366 _("Standard uninstall not possible"),
367 wxICON_EXCLAMATION
| wxYES_NO
| wxNO_DEFAULT
).ShowModal()
370 isFullUninstall
= true;
373 MESG_DIALOG(_("Uninstall cancelled by user"));
380 if (isFullUninstall
)
382 buf
.Printf(wxT("%s" PATH_SEP
".rockbox"), dir
.c_str());
385 WARN_DIALOG(_("Unable to completely remove Rockbox directory"),
386 _("Full uninstall") );
390 wxDir
* root
= new wxDir(dir
);
391 wxArrayString
* special
= new wxArrayString();
392 // Search for files for deletion in the jukebox root
393 for (i
= 0; i
< rootmatch
->GetCount(); i
++)
395 const wxString match
= (*rootmatch
)[i
];
396 root
->GetAllFiles(dir
, special
, match
, wxDIR_FILES
);
400 // Sort in reverse order so we get directories last
403 for (i
= 0; i
< special
->GetCount(); i
++)
406 if (wxDirExists((*special
)[i
]) )
408 // We don't check the return code since we don't want non
409 // empty dirs disappearing.
410 wxRmdir((*special
)[i
]);
412 } else if (wxFileExists((*special
)[i
]) )
414 if (! wxRemoveFile((*special
)[i
]) )
416 buf
.Printf(_("Can't delete %s"), (*special
)[i
].c_str());
417 WARN_DIALOG(buf
.c_str(), _("Full uninstall"));
421 // Otherwise there isn't anything there, so we don't have to worry.
426 wxString instplat
, this_path_sep
;
427 unsigned int totalfiles
, rc
;
428 totalfiles
= FilesToRemove
->GetCount();
429 FilesToRemove
->Sort(true); // Reverse alphabetical ie dirs after files
431 for (i
= 0; i
< totalfiles
; i
++)
433 // If we're running on the device, let's not delete our own
436 FilesToRemove
->Item(i
).StartsWith(wxT(PATH_SEP
442 wxString
* buf2
= new wxString
;
443 buf
.Printf("%s%s", dir
.c_str() , FilesToRemove
->Item(i
).c_str() );
444 buf2
->Format(_("Deleting %s"), buf
.c_str());
446 if (! progress
->Update((i
+ 1) * 100 / totalfiles
, *buf2
) )
448 WARN_DIALOG(_("Cancelled by user"), _("Normal Uninstall"));
453 if (wxDirExists(buf
) )
455 // If we're about to attempt to remove .rockbox. delete
456 // install data first
457 buf2
->Printf(wxT("%s" PATH_SEP
".rockbox"), dir
.c_str() );
458 if ( buf
.IsSameAs(buf2
->c_str()) )
460 buf2
->Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dir
.c_str());
464 if ( rc
= ! wxRmdir(buf
) )
466 buf
= buf
.Format(_("Can't remove directory %s"),
469 WARN_DIALOG(buf
.c_str(), _("Standard uninstall"));
471 } else if (wxFileExists(buf
) )
473 if ( rc
= ! wxRemoveFile(buf
) )
475 buf
= buf
.Format(_("Can't delete file %s"),
478 WARN_DIALOG(buf
.c_str(), _("Standard uninstall"));
483 buf
= buf
.Format(_("Can't find file or directory %s"),
485 WARN_DIALOG(buf
.c_str(), _("Standard uninstall") );
488 uninst
= uninst
.AfterFirst('\n');
492 ERR_DIALOG(_("Unable to remove some files"),
493 _("Standard uninstall")) ;
496 if (FilesToRemove
!= NULL
) delete FilesToRemove
;
500 wxLogVerbose(_("=== end Uninstall"));
505 wxString
stream_err_str(int errnum
)
510 case wxSTREAM_NO_ERROR
:
511 out
= wxT("wxSTREAM_NO_ERROR");
514 out
= wxT("wxSTREAM_EOF");
516 case wxSTREAM_WRITE_ERROR
:
517 out
= wxT("wxSTREAM_WRITE_ERROR");
519 case wxSTREAM_READ_ERROR
:
520 out
= wxT("wxSTREAM_READ_ERROR");
523 out
= wxT("UNKNOWN");
529 bool InstallRbutil(wxString dest
)
531 wxArrayString filestocopy
;
532 wxString str
, buf
, dstr
, localpath
, destdir
;
535 bool copied_exe
= false, made_rbdir
= false;
538 buf
.Printf(wxT("%s" PATH_SEP
".rockbox"), dest
.c_str() );
540 if (! wxDirExists(buf
) )
546 buf
.Printf(wxT("%s" PATH_SEP UNINSTALL_FILE
), dest
.c_str() );
547 log
= new InstallLog(buf
);
548 if (made_rbdir
) log
->WriteFile(wxT(".rockbox"), true);
550 destdir
.Printf(wxT("%s" PATH_SEP
"RockboxUtility"), dest
.c_str());
551 if (! wxDirExists(destdir
) )
553 if (! wxMkdir(destdir
, 0777) )
555 buf
.Printf(wxT("%s (%s)"),
556 _("Unable to create directory for installer"), destdir
.c_str());
557 WARN_DIALOG(buf
, _("Portable install") );
560 log
->WriteFile(wxT("RockboxUtility"), true);
563 dir
.GetAllFiles(gv
->ResourceDir
, &filestocopy
, wxT("*"),
565 if (filestocopy
.GetCount() < 1)
567 WARN_DIALOG(_("No files to copy"), _("Portable install") );
571 // Copy the contents of the program directory
572 for (i
= 0; i
< filestocopy
.GetCount(); i
++)
574 if (filestocopy
[i
].AfterLast(PATH_SEP_CHR
) == EXE_NAME
)
579 dstr
.Printf(wxT("%s" PATH_SEP
"%s"), destdir
.c_str(),
580 filestocopy
[i
].AfterLast(PATH_SEP_CHR
).c_str());
581 if (! wxCopyFile(filestocopy
[i
], dstr
) )
583 buf
.Printf(wxT("%s (%s -> %s)"),
584 _("Error copying file"), filestocopy
[i
].c_str(), dstr
.c_str());
585 WARN_DIALOG(buf
, _("Portable Install") );
589 buf
.Replace(dest
, wxEmptyString
, false);
595 str
.Printf(wxT("%s" PATH_SEP EXE_NAME
), gv
->AppDir
.c_str());
596 dstr
.Printf(wxT("%s" PATH_SEP EXE_NAME
), destdir
.c_str(),
597 filestocopy
[i
].AfterLast(PATH_SEP_CHR
).c_str());
598 if (! wxCopyFile(str
, dstr
) )
600 buf
.Printf(wxT("Can't copy program binary %s -> %s"),
601 str
.c_str(), dstr
.c_str() );
602 WARN_DIALOG(buf
, _("Portable Install") );
606 buf
.Replace(dest
, wxEmptyString
, false);
610 // Copy the local ini file so that it knows that it's a portable copy
611 gv
->UserConfig
->Flush();
612 dstr
.Printf(wxT("%s" PATH_SEP
"RockboxUtility.cfg"), destdir
.c_str());
613 if (! wxCopyFile(gv
->UserConfigFile
, dstr
) )
615 buf
.Printf(wxT("%s (%s -> %s)"),
616 _("Unable to install user config file"), gv
->UserConfigFile
.c_str(),
618 WARN_DIALOG(buf
, _("Portable Install") );
622 buf
.Replace(dest
, wxEmptyString
, false);
629 bool rm_rf(wxString file
)
631 wxLogVerbose(_("=== begin rm-rf(%s)"), file
.c_str() );
634 wxArrayString selected
;
635 wxDirTraverserIncludeDirs
wxdtid(selected
);
636 unsigned int rc
= 0, i
;
637 bool errflag
= false;
639 if (wxFileExists(file
) )
641 rc
= ! wxRemoveFile(file
);
642 } else if (wxDirExists(file
) )
644 wxDir
* dir
= new wxDir(file
);;
645 dir
->Traverse(wxdtid
);
647 // Sort into reverse alphabetical order for deletion in correct order
648 // (directories after files)
652 wxProgressDialog
* progress
= new wxProgressDialog(_("Removing files"),
653 _("Deleting files"), selected
.GetCount(), NULL
,
654 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
655 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
657 for (i
= 0; i
< selected
.GetCount(); i
++)
659 wxLogVerbose(selected
[i
]);
660 if (progress
!= NULL
)
662 buf
.Printf(_("Deleting %s"), selected
[i
].c_str() );
663 if (! progress
->Update(i
, buf
))
665 WARN_DIALOG(_("Cancelled by user"), _("Erase Files"));
671 if (wxDirExists(selected
[i
]) )
673 if (rc
= ! wxRmdir(selected
[i
]) )
675 buf
.Printf(_("Can't remove directory %s"),
676 selected
[i
].c_str());
678 WARN_DIALOG(buf
.c_str(), _("Erase files"));
680 } else if (rc
= ! wxRemoveFile(selected
[i
]) )
682 buf
.Printf(_("Error deleting file %s"), selected
[i
].c_str() );
684 WARN_DIALOG(buf
.c_str(),_("Erase files"));
690 buf
.Printf(_("Can't find expected file %s"), file
.c_str());
691 WARN_DIALOG(buf
.c_str(), _("Erase files"));
695 wxLogVerbose(_("=== end rm-rf"));
696 return rc
? true : false;