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
)
107 wxFFileInputStream
* in_file
= new wxFFileInputStream(zipname
);
108 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
110 entry
.reset(in_zip
->GetNextEntry());
112 wxString name
= entry
->GetName();
115 if( 0==name
.Cmp(wxT(".rockbox"))
116 || 0==name
.Cmp(wxT(".rockbox\\"))
117 || 0==name
.Cmp(wxT(".rockbox/")) )
122 if( name
.StartsWith(wxT(".rockbox/"))
123 || name
.StartsWith(wxT(".rockbox\\")) )
131 int DownloadURL(wxString src
, wxString dest
)
133 int input
, errnum
= 0, success
= false;
134 wxString buf
, errstr
;
135 wxLogVerbose(wxT("=== begin DownloadURL(%s,%s)"), src
.c_str(),
138 buf
= wxT("Fetching ") + src
;
139 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Downloading"),
140 buf
, 100, NULL
, wxPD_APP_MODAL
|
141 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
142 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
143 progress
->SetSize(500,200);
148 wxURL
* in_http
= new wxURL(src
);
150 if(gv
->proxy_url
!= wxT(""))
151 in_http
->SetProxy(gv
->proxy_url
);
153 if (in_http
->GetError() == wxURL_NOERR
)
156 wxFFileOutputStream
* os
= new wxFFileOutputStream(dest
);
160 wxInputStream
* is
= in_http
->GetInputStream();
164 size_t filesize
= is
->GetSize();
168 char buffer
[FILE_BUFFER_SIZE
+ 1];
173 is
->Read(buffer
, FILE_BUFFER_SIZE
);
177 os
->Write(buffer
, is
->LastRead());
181 current
+= os
->LastWrite();
182 if (!progress
->Update(current
* 100 / filesize
))
184 errstr
= wxT("Download aborted by user");
191 errnum
= os
->GetLastError();
192 errstr
= wxT("Can't write to output stream (")
193 + stream_err_str(errnum
) + wxT(")");
200 errnum
= is
->GetLastError();
201 if (errnum
== wxSTREAM_EOF
)
206 errstr
= wxT("Can't read from input stream (")
207 + stream_err_str(errnum
) + wxT(")");
214 errnum
= os
->GetLastError();
215 errstr
= wxT("Can't close output file (")
216 + stream_err_str(errnum
) + wxT(")");
221 if (! errnum
) success
= true;
225 errnum
= is
->GetLastError();
226 errstr
= wxT("Can't get input stream size (")
227 + stream_err_str(errnum
) + wxT(")");
231 errnum
= in_http
->GetError();
232 errstr
.Printf(wxT("Can't get input stream (%d)"), errnum
);
237 errnum
= os
->GetLastError();
238 errstr
= wxT("Can't create output stream (")
239 + stream_err_str(errnum
) + wxT(")");
244 errstr
.Printf(wxT("Can't open URL %s (%d)"), src
.c_str(),
245 in_http
->GetError() );
254 if (errnum
== 0) errnum
= 999;
257 ERR_DIALOG(errstr
+ wxT(" reading\n") + src
, wxT("Download URL"));
260 ERR_DIALOG(errstr
+ wxT("writing to download\n/") + dest
,
261 wxT("Download URL"));
266 wxLogVerbose(wxT("=== end DownloadURL"));
270 int UnzipFile(wxString src
, wxString destdir
, bool isInstall
)
274 wxString in_str
, progress_msg
, buf
,subdir
;
275 int errnum
= 0, curfile
= 0, totalfiles
= 0;
276 InstallLog
* log
= NULL
;
278 wxLogVerbose(wxT("===begin UnzipFile(%s,%s,%i)"),
279 src
.c_str(), destdir
.c_str(), isInstall
);
281 wxFFileInputStream
* in_file
= new wxFFileInputStream(src
);
282 wxZipInputStream
* in_zip
= new wxZipInputStream(*in_file
);
285 if (! in_zip
->IsOk() )
287 errnum
= in_zip
->GetLastError();
288 ERR_DIALOG(wxT("Can't open ZIP stream ") + src
289 + wxT(" for reading (") + stream_err_str(errnum
)
290 + wxT(")"), wxT("Unzip File") );
296 totalfiles
= in_zip
->GetTotalEntries();
297 if (! in_zip
->IsOk() )
299 errnum
= in_zip
->GetLastError();
300 ERR_DIALOG( wxT("Error Getting total ZIP entries for ")
301 + src
+ wxT(" (") + stream_err_str(errnum
) + wxT(")"),
309 errnum
= in_file
->GetLastError();
310 ERR_DIALOG(wxT("Can't open ") + src
+ wxT(" (")
311 + stream_err_str(errnum
) + wxT(")"), wxT("Unzip File") );
317 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Unpacking archive"),
318 wxT("Preparing to unpack the downloaded files to your audio"
319 "device"), totalfiles
, NULL
, wxPD_APP_MODAL
|
320 wxPD_AUTO_HIDE
| wxPD_SMOOTH
| wxPD_ELAPSED_TIME
|
321 wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
324 // We're not overly worried if the logging fails
327 log
= new InstallLog(destdir
+ wxT("" PATH_SEP UNINSTALL_FILE
));
331 (entry
.reset(in_zip
->GetNextEntry()), entry
.get() != NULL
) )
336 wxString name
= entry
->GetName();
338 progress_msg
= wxT("Unpacking ") + name
;
339 if (! progress
->Update(curfile
, progress_msg
) )
341 MESG_DIALOG(wxT("Unpacking cancelled by user"));
346 in_str
= destdir
+ wxT("" PATH_SEP
) + name
;
348 subdir
= wxPathOnly(in_str
);
349 if(!(wxDirExists(subdir
)))
351 if (! wxMkdir(subdir
, 0777) )
353 buf
= wxT("Unable to create directory ") + subdir
;
357 log
->WriteFile(subdir
, true); // Directory
362 if(!wxDirExists(name
))
364 if(!wxMkdir(name
, 0777) )
366 buf
= wxT("Unable to create directory ") + name
;
371 log
->WriteFile(name
, true); // Directory
372 continue; // this is just a directory, nothing else to do
375 // its a file, copy it
376 wxFFileOutputStream
* out
= new wxFFileOutputStream(in_str
);
379 buf
= wxT("Can't open file ") + in_str
+ wxT(" for writing");
383 } else if (isInstall
)
385 log
->WriteFile(name
);
390 buf
.Printf(wxT("Can't write to %s (%d)"), in_str
.c_str(),
391 errnum
= out
->GetLastError() );
394 if (!in_zip
->IsOk() && ! in_file
->GetLastError() == wxSTREAM_EOF
)
396 buf
.Printf(wxT("Can't read from %s (%d)"), src
.c_str(),
397 errnum
= in_file
->GetLastError() );
400 if (! out
->Close() && errnum
== 0)
402 buf
.Printf(wxT("Unable to close %s (%d)"), in_str
.c_str(),
403 errnum
= out
->GetLastError() );
411 delete in_zip
; delete in_file
; delete progress
;
415 ERR_DIALOG(buf
, wxT("Unzip File"));
419 wxLogVerbose(wxT("=== end UnzipFile"));
424 int Uninstall(const wxString dir
, bool isFullUninstall
) {
425 wxString buf
, uninst
;
427 bool errflag
= false;
428 InstallLog
*log
= NULL
;
429 wxArrayString
* FilesToRemove
= NULL
;
431 wxLogVerbose(wxT("=== begin Uninstall(%s,%i)"), dir
.c_str(), isFullUninstall
);
433 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Uninstalling"),
434 wxT("Reading uninstall data from jukebox"), 100, NULL
,
435 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
436 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
439 if (! isFullUninstall
)
442 buf
= dir
+ wxT("" PATH_SEP UNINSTALL_FILE
);
443 log
= new InstallLog(buf
, false); // Don't create the log
444 FilesToRemove
= log
->GetInstalledFiles();
447 if (FilesToRemove
== NULL
|| FilesToRemove
->GetCount() < 1) {
449 if ( wxMessageDialog(NULL
,
450 wxT("Rockbox Utility can't find any uninstall data on this "
452 "Would you like to attempt a full uninstall?\n"
453 "(WARNING: A full uninstall removes all files in your Rockbox "
455 wxT("Standard uninstall not possible"),
456 wxICON_EXCLAMATION
| wxYES_NO
| wxNO_DEFAULT
).ShowModal()
459 isFullUninstall
= true;
462 MESG_DIALOG(wxT("Uninstall cancelled by user"));
469 if (isFullUninstall
)
471 buf
= dir
+ wxT("" PATH_SEP
".rockbox");
474 WARN_DIALOG(wxT("Unable to completely remove Rockbox directory"),
475 wxT("Full uninstall") );
479 wxDir
* root
= new wxDir(dir
);
480 wxArrayString
* special
= new wxArrayString();
481 // Search for files for deletion in the jukebox root
482 for (i
= 0; i
< rootmatch
->GetCount(); i
++)
484 const wxString match
= (*rootmatch
)[i
];
485 root
->GetAllFiles(dir
, special
, match
, wxDIR_FILES
);
489 // Sort in reverse order so we get directories last
492 for (i
= 0; i
< special
->GetCount(); i
++)
495 if (wxDirExists((*special
)[i
]) )
497 // We don't check the return code since we don't want non
498 // empty dirs disappearing.
499 wxRmdir((*special
)[i
]);
501 } else if (wxFileExists((*special
)[i
]) )
503 if (! wxRemoveFile((*special
)[i
]) )
505 WARN_DIALOG(wxT("Can't delete ") + (*special
)[i
],
506 wxT("Full uninstall"));
510 // Otherwise there isn't anything there, so we don't have to worry.
515 wxString instplat
, this_path_sep
;
516 unsigned int totalfiles
, rc
;
517 totalfiles
= FilesToRemove
->GetCount();
518 FilesToRemove
->Sort(true); // Reverse alphabetical ie dirs after files
520 for (i
= 0; i
< totalfiles
; i
++)
522 // If we're running on the device, let's not delete our own
525 FilesToRemove
->Item(i
).StartsWith(PATH_SEP
526 wxT("RockboxUtility")) )
531 wxString
* buf2
= new wxString
;
532 buf
= dir
+ FilesToRemove
->Item(i
);
533 buf2
->Format(wxT("Deleting %s"), buf
.c_str());
535 if (! progress
->Update((i
+ 1) * 100 / totalfiles
, *buf2
) )
537 WARN_DIALOG(wxT("Cancelled by user"), wxT("Normal Uninstall"));
542 if (wxDirExists(buf
) )
544 // If we're about to attempt to remove .rockbox. delete
545 // install data first
546 *buf2
= dir
+ wxT("" PATH_SEP
".rockbox");
547 if ( buf
.IsSameAs(buf2
->c_str()) )
549 *buf2
= dir
+wxT("" PATH_SEP UNINSTALL_FILE
);
553 if ( (rc
= ! wxRmdir(buf
)) )
555 buf
= buf
.Format(wxT("Can't remove directory %s"),
558 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
560 } else if (wxFileExists(buf
) )
562 if ( (rc
= ! wxRemoveFile(buf
)) )
564 buf
= buf
.Format(wxT("Can't delete file %s"),
567 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall"));
572 buf
= buf
.Format(wxT("Can't find file or directory %s"),
574 WARN_DIALOG(buf
.c_str(), wxT("Standard uninstall") );
577 uninst
= uninst
.AfterFirst('\n');
581 ERR_DIALOG(wxT("Unable to remove some files"),
582 wxT("Standard uninstall")) ;
585 if (FilesToRemove
!= NULL
) delete FilesToRemove
;
589 wxLogVerbose(wxT("=== end Uninstall"));
594 wxString
stream_err_str(int errnum
)
599 case wxSTREAM_NO_ERROR
:
600 out
= wxT("wxSTREAM_NO_ERROR");
603 out
= wxT("wxSTREAM_EOF");
605 case wxSTREAM_WRITE_ERROR
:
606 out
= wxT("wxSTREAM_WRITE_ERROR");
608 case wxSTREAM_READ_ERROR
:
609 out
= wxT("wxSTREAM_READ_ERROR");
612 out
= wxT("UNKNOWN");
618 bool InstallRbutil(wxString dest
)
620 wxArrayString filestocopy
;
621 wxString str
, buf
, dstr
, localpath
, destdir
;
624 bool copied_exe
= false, made_rbdir
= false;
627 buf
= dest
+ wxT("" PATH_SEP
".rockbox");
629 if (! wxDirExists(buf
) )
635 buf
= dest
+ wxT("" PATH_SEP UNINSTALL_FILE
);
636 log
= new InstallLog(buf
);
637 if (made_rbdir
) log
->WriteFile(wxT(".rockbox"), true);
639 destdir
= dest
+ wxT("" PATH_SEP
"RockboxUtility");
640 if (! wxDirExists(destdir
) )
642 if (! wxMkdir(destdir
, 0777) )
644 WARN_DIALOG( wxT("Unable to create directory for installer (")
645 + destdir
+ wxT(")"), wxT("Portable install") );
648 log
->WriteFile(wxT("RockboxUtility"), true);
651 dir
.GetAllFiles(gv
->ResourceDir
, &filestocopy
, wxT("*"),
653 if (filestocopy
.GetCount() < 1)
655 WARN_DIALOG(wxT("No files to copy"), wxT("Portable install") );
659 // Copy the contents of the program directory
660 for (i
= 0; i
< filestocopy
.GetCount(); i
++)
662 if (filestocopy
[i
].AfterLast(PATH_SEP_CHR
) == EXE_NAME
)
667 dstr
= destdir
+ wxT("" PATH_SEP
)
668 + filestocopy
[i
].AfterLast(PATH_SEP_CHR
);
669 if (! wxCopyFile(filestocopy
[i
], dstr
) )
671 WARN_DIALOG( wxT("Error copying file (")
672 + filestocopy
[i
].c_str() + wxT(" -> ")
673 + dstr
+ wxT(")"), wxT("Portable Install") );
677 buf
.Replace(dest
, wxEmptyString
, false);
683 str
= gv
->AppDir
+ wxT("" PATH_SEP EXE_NAME
);
684 dstr
= destdir
+ wxT("" PATH_SEP EXE_NAME
);
685 if (! wxCopyFile(str
, dstr
) )
687 WARN_DIALOG(wxT("Can't copy program binary ")
688 + str
+ wxT(" -> ") + dstr
, wxT("Portable Install") );
692 buf
.Replace(dest
, wxEmptyString
, false);
696 // Copy the local ini file so that it knows that it's a portable copy
697 gv
->UserConfig
->Flush();
698 dstr
= destdir
+ wxT("" PATH_SEP
"RockboxUtility.cfg");
699 if (! wxCopyFile(gv
->UserConfigFile
, dstr
) )
701 WARN_DIALOG(wxT("Unable to install user config file (")
702 + gv
->UserConfigFile
+ wxT(" -> ") + dstr
+ wxT(")"),
703 wxT("Portable Install") );
707 buf
.Replace(dest
, wxEmptyString
, false);
714 bool rm_rf(wxString file
)
716 wxLogVerbose(wxT("=== begin rm-rf(%s)"), file
.c_str() );
719 wxArrayString selected
;
720 wxDirTraverserIncludeDirs
wxdtid(selected
);
721 unsigned int rc
= 0, i
;
722 bool errflag
= false;
724 if (wxFileExists(file
) )
726 rc
= ! wxRemoveFile(file
);
727 } else if (wxDirExists(file
) )
729 wxDir
* dir
= new wxDir(file
);;
730 dir
->Traverse(wxdtid
);
732 // Sort into reverse alphabetical order for deletion in correct order
733 // (directories after files)
737 wxProgressDialog
* progress
= new wxProgressDialog(wxT("Removing files"),
738 wxT("Deleting files"), selected
.GetCount(), NULL
,
739 wxPD_APP_MODAL
| wxPD_AUTO_HIDE
| wxPD_SMOOTH
|
740 wxPD_ELAPSED_TIME
| wxPD_REMAINING_TIME
| wxPD_CAN_ABORT
);
742 for (i
= 0; i
< selected
.GetCount(); i
++)
744 wxLogVerbose(selected
[i
]);
745 if (progress
!= NULL
)
747 buf
= wxT("Deleting ") + selected
[i
];
748 if (! progress
->Update(i
, buf
))
750 WARN_DIALOG(wxT("Cancelled by user"), wxT("Erase Files"));
756 if (wxDirExists(selected
[i
]) )
758 if ((rc
= ! wxRmdir(selected
[i
])) )
761 WARN_DIALOG(wxT("Can't remove directory ") + selected
[i
],
764 } else if ((rc
= ! wxRemoveFile(selected
[i
])) )
767 WARN_DIALOG(wxT("Error deleting file ") + selected
[i
],
774 WARN_DIALOG(wxT("Can't find expected file ") + file
,
779 wxLogVerbose(wxT("=== end rm-rf"));
780 return rc
? true : false;