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"
24 /* this function gets a Bitmap from embedded memory */
25 wxBitmap
wxGetBitmapFromMemory(const unsigned char *data
,int length
)
27 wxMemoryInputStream
istream( data
,length
);
28 return wxBitmap(wxImage(istream
, wxBITMAP_TYPE_ANY
, -1), -1);
31 // This class allows us to return directories as well as files to
33 class wxDirTraverserIncludeDirs
: public wxDirTraverser
36 wxDirTraverserIncludeDirs(wxArrayString
& files
) : m_files(files
) { }
38 virtual wxDirTraverseResult
OnFile(const wxString
& filename
)
40 m_files
.Add(filename
);
41 return wxDIR_CONTINUE
;
44 virtual wxDirTraverseResult
OnDir(const wxString
& dirname
)
47 return wxDIR_CONTINUE
;
51 wxArrayString
& m_files
;
54 wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry
);
56 const wxChar
* _rootmatch
[] = {
61 wxT("battery_bench.txt"),
64 const wxArrayString
* rootmatch
= new wxArrayString(
65 (size_t) (sizeof(_rootmatch
) / sizeof(wxChar
*)), _rootmatch
);
67 bool InstallTheme(wxString Themesrc
)
69 wxString dest
,src
,err
;
71 int pos
= Themesrc
.Find('/',true);
72 wxString themename
= Themesrc
.SubString(pos
+1,Themesrc
.Length());
74 src
= gv
->themes_url
+ wxT("/") + Themesrc
;
75 dest
= gv
->stdpaths
->GetUserDataDir()
76 + wxT("" PATH_SEP
"download" PATH_SEP
) + themename
;
77 if( DownloadURL(src
, dest
) )
80 ERR_DIALOG(wxT("Unable to download ") + src
, wxT("Install Theme"));
86 ERR_DIALOG(wxT("The Zip ") + dest
87 + wxT(" does not contain the correct dir structure"),
88 wxT("Install Theme"));
92 if(UnzipFile(dest
,gv
->curdestdir
, true))
94 ERR_DIALOG(wxT("Unable to unzip ") + dest
+ wxT(" to ")
95 + gv
->curdestdir
, wxT("Install Theme"));
102 bool checkZip(wxString zipname
)
106 wxFFileInputStream
* in_file
= new wxFFileInputStream(zipname
);
107 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
109 entry
.reset(in_zip
->GetNextEntry());
111 wxString name
= entry
->GetName();
114 if(name
.Contains(wxT(".rockbox")))
122 int DownloadURL(wxString src
, wxString dest
)
124 int input
, errnum
= 0, success
= false;
125 wxString buf
, errstr
;
126 wxLogVerbose(wxT("=== begin DownloadURL(%s,%s)"), src
.c_str(),
129 buf
= wxT("Fetching ") + src
;
130 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Downloading"),
131 buf
, 100, NULL
, wxPD_APP_MODAL
|
132 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
133 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
134 progress
->SetSize(500,200);
139 wxURL
* in_http
= new wxURL(src
);
141 if(gv
->proxy_url
!= wxT(""))
142 in_http
->SetProxy(gv
->proxy_url
);
144 if (in_http
->GetError() == wxURL_NOERR
)
147 wxFFileOutputStream
* os
= new wxFFileOutputStream(dest
);
151 wxInputStream
* is
= in_http
->GetInputStream();
155 size_t filesize
= is
->GetSize();
159 char buffer
[FILE_BUFFER_SIZE
+ 1];
164 is
->Read(buffer
, FILE_BUFFER_SIZE
);
168 os
->Write(buffer
, is
->LastRead());
172 current
+= os
->LastWrite();
173 if (!progress
->Update(current
* 100 / filesize
))
175 errstr
= wxT("Download aborted by user");
182 errnum
= os
->GetLastError();
183 errstr
= wxT("Can't write to output stream (")
184 + stream_err_str(errnum
) + wxT(")");
191 errnum
= is
->GetLastError();
192 if (errnum
== wxSTREAM_EOF
)
197 errstr
= wxT("Can't read from input stream (")
198 + stream_err_str(errnum
) + wxT(")");
205 errnum
= os
->GetLastError();
206 errstr
= wxT("Can't close output file (")
207 + stream_err_str(errnum
) + wxT(")");
212 if (! errnum
) success
= true;
216 errnum
= is
->GetLastError();
217 errstr
= wxT("Can't get input stream size (")
218 + stream_err_str(errnum
) + wxT(")");
222 errnum
= in_http
->GetError();
223 errstr
.Printf(wxT("Can't get input stream (%d)"), errnum
);
228 errnum
= os
->GetLastError();
229 errstr
= wxT("Can't create output stream (")
230 + stream_err_str(errnum
) + wxT(")");
235 errstr
.Printf(wxT("Can't open URL %s (%d)"), src
.c_str(),
236 in_http
->GetError() );
245 if (errnum
== 0) errnum
= 999;
248 ERR_DIALOG(errstr
+ wxT(" reading\n") + src
, wxT("Download URL"));
251 ERR_DIALOG(errstr
+ wxT("writing to download\n/") + dest
,
252 wxT("Download URL"));
257 wxLogVerbose(wxT("=== end DownloadURL"));
261 int UnzipFile(wxString src
, wxString destdir
, bool isInstall
)
264 wxString in_str
, progress_msg
, buf
;
265 int errnum
= 0, curfile
= 0, totalfiles
= 0;
266 InstallLog
* log
= NULL
;
268 wxLogVerbose(wxT("===begin UnzipFile(%s,%s,%i)"),
269 src
.c_str(), destdir
.c_str(), isInstall
);
271 wxFFileInputStream
* in_file
= new wxFFileInputStream(src
);
272 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
275 if (! in_zip
->IsOk() )
277 errnum
= in_zip
->GetLastError();
278 ERR_DIALOG(wxT("Can't open ZIP stream ") + src
279 + wxT(" for reading (") + stream_err_str(errnum
)
280 + wxT(")"), wxT("Unzip File") );
286 totalfiles
= in_zip
->GetTotalEntries();
287 if (! in_zip
->IsOk() )
289 errnum
= in_zip
->GetLastError();
290 ERR_DIALOG( wxT("Error Getting total ZIP entries for ")
291 + src
+ wxT(" (") + stream_err_str(errnum
) + wxT(")"),
299 errnum
= in_file
->GetLastError();
300 ERR_DIALOG(wxT("Can't open ") + src
+ wxT(" (")
301 + stream_err_str(errnum
) + wxT(")"), wxT("Unzip File") );
307 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Unpacking archive"),
308 wxT("Preparing to unpack the downloaded files to your audio"
309 "device"), totalfiles
, NULL
, wxPD_APP_MODAL
|
310 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
311 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
314 // We're not overly worried if the logging fails
317 log
= new InstallLog(destdir
+ wxT("" PATH_SEP UNINSTALL_FILE
));
321 (entry
.reset(in_zip
->GetNextEntry()), entry
.get() != NULL
) )
325 wxString name
= entry
->GetName();
326 progress_msg
= wxT("Unpacking ") + name
;
327 if (! progress
->Update(curfile
, progress_msg
) ) {
328 MESG_DIALOG(wxT("Unpacking cancelled by user"));
333 in_str
= destdir
+ wxT("" PATH_SEP
) + name
;
335 if (entry
->IsDir() ) {
336 if (!wxDirExists(in_str
) ) {
337 if (! wxMkdir(in_str
, 0777) ) {
338 buf
= wxT("Unable to create directory ") + in_str
;
343 log
->WriteFile(name
, true); // Directory
347 wxFFileOutputStream
* out
= new wxFFileOutputStream(in_str
);
350 buf
= wxT("Can't open file ") + in_str
+ wxT(" for writing");
353 } else if (isInstall
)
355 log
->WriteFile(name
);
360 buf
.Printf(wxT("Can't write to %s (%d)"), in_str
.c_str(),
361 errnum
= out
->GetLastError() );
364 if (!in_zip
->IsOk() && ! in_file
->GetLastError() == wxSTREAM_EOF
)
366 buf
.Printf(wxT("Can't read from %s (%d)"), src
.c_str(),
367 errnum
= in_file
->GetLastError() );
370 if (! out
->Close() && errnum
== 0)
372 buf
.Printf(wxT("Unable to close %s (%d)"), in_str
.c_str(),
373 errnum
= out
->GetLastError() );
381 delete in_zip
; delete in_file
; delete progress
;
385 ERR_DIALOG(buf
, wxT("Unzip File"));
389 wxLogVerbose(wxT("=== end UnzipFile"));
393 int Uninstall(const wxString dir
, bool isFullUninstall
) {
394 wxString buf
, uninst
;
396 bool errflag
= false;
397 InstallLog
*log
= NULL
;
398 wxArrayString
* FilesToRemove
= NULL
;
400 wxLogVerbose(wxT("=== begin Uninstall(%s,%i)"), dir
.c_str(), isFullUninstall
);
402 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Uninstalling"),
403 wxT("Reading uninstall data from jukebox"), 100, NULL
,
404 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
405 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
408 if (! isFullUninstall
)
411 buf
= dir
+ wxT("" PATH_SEP UNINSTALL_FILE
);
412 log
= new InstallLog(buf
, false); // Don't create the log
413 FilesToRemove
= log
->GetInstalledFiles();
416 if (FilesToRemove
== NULL
|| FilesToRemove
->GetCount() < 1) {
418 if ( wxMessageDialog(NULL
,
419 wxT("Rockbox Utility can't find any uninstall data on this "
421 "Would you like to attempt a full uninstall?\n"
422 "(WARNING: A full uninstall removes all files in your Rockbox "
424 wxT("Standard uninstall not possible"),
425 wxICON_EXCLAMATION
| wxYES_NO
| wxNO_DEFAULT
).ShowModal()
428 isFullUninstall
= true;
431 MESG_DIALOG(wxT("Uninstall cancelled by user"));
438 if (isFullUninstall
)
440 buf
= dir
+ wxT("" PATH_SEP
".rockbox");
443 WARN_DIALOG(wxT("Unable to completely remove Rockbox directory"),
444 wxT("Full uninstall") );
448 wxDir
* root
= new wxDir(dir
);
449 wxArrayString
* special
= new wxArrayString();
450 // Search for files for deletion in the jukebox root
451 for (i
= 0; i
< rootmatch
->GetCount(); i
++)
453 const wxString match
= (*rootmatch
)[i
];
454 root
->GetAllFiles(dir
, special
, match
, wxDIR_FILES
);
458 // Sort in reverse order so we get directories last
461 for (i
= 0; i
< special
->GetCount(); i
++)
464 if (wxDirExists((*special
)[i
]) )
466 // We don't check the return code since we don't want non
467 // empty dirs disappearing.
468 wxRmdir((*special
)[i
]);
470 } else if (wxFileExists((*special
)[i
]) )
472 if (! wxRemoveFile((*special
)[i
]) )
474 WARN_DIALOG(wxT("Can't delete ") + (*special
)[i
],
475 wxT("Full uninstall"));
479 // Otherwise there isn't anything there, so we don't have to worry.
484 wxString instplat
, this_path_sep
;
485 unsigned int totalfiles
, rc
;
486 totalfiles
= FilesToRemove
->GetCount();
487 FilesToRemove
->Sort(true); // Reverse alphabetical ie dirs after files
489 for (i
= 0; i
< totalfiles
; i
++)
491 // If we're running on the device, let's not delete our own
494 FilesToRemove
->Item(i
).StartsWith(PATH_SEP
495 wxT("RockboxUtility")) )
500 wxString
* buf2
= new wxString
;
501 buf
= dir
+ FilesToRemove
->Item(i
);
502 buf2
->Format(wxT("Deleting %s"), buf
.c_str());
504 if (! progress
->Update((i
+ 1) * 100 / totalfiles
, *buf2
) )
506 WARN_DIALOG(wxT("Cancelled by user"), wxT("Normal Uninstall"));
511 if (wxDirExists(buf
) )
513 // If we're about to attempt to remove .rockbox. delete
514 // install data first
515 *buf2
= dir
+ wxT("" PATH_SEP
".rockbox");
516 if ( buf
.IsSameAs(buf2
->c_str()) )
518 *buf2
= dir
+wxT("" PATH_SEP UNINSTALL_FILE
);
522 if ( (rc
= ! wxRmdir(buf
)) )
524 buf
= buf
.Format(wxT("Can't remove directory %s"),
527 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
529 } else if (wxFileExists(buf
) )
531 if ( (rc
= ! wxRemoveFile(buf
)) )
533 buf
= buf
.Format(wxT("Can't delete file %s"),
536 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
541 buf
= buf
.Format(wxT("Can't find file or directory %s"),
543 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall") );
546 uninst
= uninst
.AfterFirst('\n');
550 ERR_DIALOG(wxT("Unable to remove some files"),
551 wxT("Standard uninstall")) ;
554 if (FilesToRemove
!= NULL
) delete FilesToRemove
;
558 wxLogVerbose(wxT("=== end Uninstall"));
563 wxString
stream_err_str(int errnum
)
568 case wxSTREAM_NO_ERROR
:
569 out
= wxT("wxSTREAM_NO_ERROR");
572 out
= wxT("wxSTREAM_EOF");
574 case wxSTREAM_WRITE_ERROR
:
575 out
= wxT("wxSTREAM_WRITE_ERROR");
577 case wxSTREAM_READ_ERROR
:
578 out
= wxT("wxSTREAM_READ_ERROR");
581 out
= wxT("UNKNOWN");
587 bool InstallRbutil(wxString dest
)
589 wxArrayString filestocopy
;
590 wxString str
, buf
, dstr
, localpath
, destdir
;
593 bool copied_exe
= false, made_rbdir
= false;
596 buf
= dest
+ wxT("" PATH_SEP
".rockbox");
598 if (! wxDirExists(buf
) )
604 buf
= dest
+ wxT("" PATH_SEP UNINSTALL_FILE
);
605 log
= new InstallLog(buf
);
606 if (made_rbdir
) log
->WriteFile(wxT(".rockbox"), true);
608 destdir
= dest
+ wxT("" PATH_SEP
"RockboxUtility");
609 if (! wxDirExists(destdir
) )
611 if (! wxMkdir(destdir
, 0777) )
613 WARN_DIALOG( wxT("Unable to create directory for installer (")
614 + destdir
+ wxT(")"), wxT("Portable install") );
617 log
->WriteFile(wxT("RockboxUtility"), true);
620 dir
.GetAllFiles(gv
->ResourceDir
, &filestocopy
, wxT("*"),
622 if (filestocopy
.GetCount() < 1)
624 WARN_DIALOG(wxT("No files to copy"), wxT("Portable install") );
628 // Copy the contents of the program directory
629 for (i
= 0; i
< filestocopy
.GetCount(); i
++)
631 if (filestocopy
[i
].AfterLast(PATH_SEP_CHR
) == EXE_NAME
)
636 dstr
= destdir
+ wxT("" PATH_SEP
)
637 + filestocopy
[i
].AfterLast(PATH_SEP_CHR
);
638 if (! wxCopyFile(filestocopy
[i
], dstr
) )
640 WARN_DIALOG( wxT("Error copying file (")
641 + filestocopy
[i
].c_str() + wxT(" -> ")
642 + dstr
+ wxT(")"), wxT("Portable Install") );
646 buf
.Replace(dest
, wxEmptyString
, false);
652 str
= gv
->AppDir
+ wxT("" PATH_SEP EXE_NAME
);
653 dstr
= destdir
+ wxT("" PATH_SEP EXE_NAME
);
654 if (! wxCopyFile(str
, dstr
) )
656 WARN_DIALOG(wxT("Can't copy program binary ")
657 + str
+ wxT(" -> ") + dstr
, wxT("Portable Install") );
661 buf
.Replace(dest
, wxEmptyString
, false);
665 // Copy the local ini file so that it knows that it's a portable copy
666 gv
->UserConfig
->Flush();
667 dstr
= destdir
+ wxT("" PATH_SEP
"RockboxUtility.cfg");
668 if (! wxCopyFile(gv
->UserConfigFile
, dstr
) )
670 WARN_DIALOG(wxT("Unable to install user config file (")
671 + gv
->UserConfigFile
+ wxT(" -> ") + dstr
+ wxT(")"),
672 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
= wxT("Deleting ") + selected
[i
];
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
])) )
730 WARN_DIALOG(wxT("Can't remove directory ") + selected
[i
],
733 } else if ((rc
= ! wxRemoveFile(selected
[i
])) )
736 WARN_DIALOG(wxT("Error deleting file ") + selected
[i
],
743 WARN_DIALOG(wxT("Can't find expected file ") + file
,
748 wxLogVerbose(wxT("=== end rm-rf"));
749 return rc
? true : false;