/* seemingly good start of an automagical way to mount a user pack based on the folder structure */ CString UserPackManager::GetPackMountPoint( const CString &sPack ) { enum UserPackMountType { UPACK_MOUNT_ROOT, UPACK_MOUNT_SONGS }; RageFileDriverZip *pZip = new RageFileDriverZip; CHECKPOINT_M( sPack ); // it should already be a valid zip by now... ASSERT( pZip->Load( sPack ) ); UserPackMountType upmt = UPACK_MOUNT_SONGS; CStringArray asRootEntries; pZip->GetDirListing( "/", asRootEntries, true, false ); SAFE_DELETE( pZip ); // if we find a StepMania root folder, mount it as one for( unsigned i = 0; i < asRootEntries.size(); ++i ) { for( unsigned j = 0; j < ARRAYLEN(asRootDirs); j++ ) { if ( asRootEntries[i].CompareNoCase( asRootDirs[j] ) == 0 ) return "/"; } } /* for now, assume a Songs-only pack if the root dirs aren't there */ return "/Songs"; }
BOOL CSMPackageInstallDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here DialogUtil::LocalizeDialogAndContents( *this ); DialogUtil::SetHeaderFont( *this, IDC_STATIC_HEADER_TEXT ); // mount the zip RageFileOsAbsolute file; if( !file.Open(m_sPackagePath) ) { Dialog::OK( ssprintf(COULD_NOT_OPEN_FILE.GetValue(),m_sPackagePath.c_str()) ); exit(1); // better way to abort? } RageFileDriverZip zip; if( !zip.Load(&file) ) { Dialog::OK( ssprintf(IS_NOT_A_VALID_ZIP.GetValue(),m_sPackagePath.c_str()) ); exit(1); // better way to abort? } // // Set the text of the first Edit box // RString sMessage1 = "\t" + m_sPackagePath; CEdit* pEdit1 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE1); pEdit1->SetWindowText( sMessage1 ); // // Set the text of the second Edit box // { vector<RString> vs; GetSmzipFilesToExtract( zip, vs ); CEdit* pEdit2 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE2); RString sText = "\t" + join( "\r\n\t", vs ); pEdit2->SetWindowText( sText ); } RefreshInstallationList(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
bool UserPackManager::IsPackMountable( const CString &sPack, CString &sError ) { RageFileDriverZip *pZip = new RageFileDriverZip; if ( !pZip->Load(sPack) ) { sError = "not a valid zip file"; SAFE_DELETE( pZip ); return false; } for( unsigned i = 0; i < NUM_BLACKLISTED_FOLDERS && BLACKLISTED_FOLDERS[i] != NULL; i++ ) { CString sDir = CString("/") + BLACKLISTED_FOLDERS[i]; CStringArray sDirListing; pZip->GetDirListing( sDir, sDirListing, false, true ); int iListSize = sDirListing.size(); // if any blacklisted folders exist, reject the pack if ( iListSize > 0 ) { sError = ssprintf( "blacklisted folder: %s", BLACKLISTED_FOLDERS[i] ); SAFE_DELETE( pZip ); return false; } } // do not add if it's just folders of individual songs without a group folder CStringArray asRootFolders; pZip->GetDirListing( "/*", asRootFolders, true, false ); for( unsigned i = 0; i < asRootFolders.size(); i++ ) { CStringArray asFiles; pZip->GetDirListing( "/" + asRootFolders[i] + "/*.sm", asFiles, false, false ); pZip->GetDirListing( "/" + asRootFolders[i] + "/*.dwi", asFiles, false, false ); if ( asFiles.size() > 0 ) { sError = "Package is not a group folder package.\nPlease add songs to a single group folder.\n(i.e. {Group Name}/{Song Folder}/Song.sm)"; SAFE_DELETE( pZip ); return false; } } SAFE_DELETE( pZip ); return true; }
void ScreenArcadePatch::PatchMain() { m_State = PATCH_CHECKING; /* NOTE: we used to look for OpenITG prefixed updates also, but the * original ITG binary does not, so if we want people to be able to * upgrade directly from ITG to OITG, we have to continue to use the * "ITG 2 " prefix. Sad times. */ /* set up patterns to match */ CStringArray vsPatterns; vsPatterns.push_back( "ITG 2 *.itg" ); /* check to see if either player has patches */ PlayerNumber pn = PLAYER_INVALID; /* HasPatch() will early abort for us, due to the size() check, * if P1 and P2 both have patches. We just want the first one. */ FOREACH_PlayerNumber( p ) if( this->HasPatch(p, vsPatterns) ) pn = p; /* no matches on either card. */ if( pn == PLAYER_INVALID ) { m_State = PATCH_NONE; return; } /* set the help text to the patch name, blank the patch text */ m_textHelp->SetText( m_vsPatches[0] ); PATCH_TEXT( "" ); /* set up the key paths we want to verify against */ CStringArray vsRSAPaths; vsRSAPaths.push_back( "Data/Patch-OpenITG.rsa" ); vsRSAPaths.push_back( "Data/Patch.rsa" ); /* create the path for the patch file */ CString sPatchFile = m_sProfileDir + m_vsPatches[0]; // copy the patch file into memory // TODO: see if we can FILEMAN->GetFileDriver( "/@mem/" ). m_MemDriver = new RageFileDriverMem; int iError = 0; m_PatchFile = m_MemDriver->Open( ITG_TEMP_FILE, RageFile::WRITE, iError ); if( iError != 0 ) { STATE_TEXT( ssprintf("Failed to open temporary file:\n%s", strerror(iError)) ); m_State = PATCH_ERROR; } /* give up to an hour for the data to copy */ MEMCARDMAN->MountCard( pn, 3600 ); RageFile patch; if( !patch.Open(sPatchFile) ) { STATE_TEXT( ssprintf("Failed to open patch file (%s):\n%s", sPatchFile.c_str(), patch.GetError().c_str()) ); m_State = PATCH_ERROR; } if( m_State == PATCH_ERROR ) { MEMCARDMAN->UnmountCard(pn); return; } CString sError; if( FileCopy( patch, *m_PatchFile, sError, &UpdateProgress) ) { STATE_TEXT( "Patch copied! Checking..." ); PATCH_TEXT( "" ); } else { STATE_TEXT( ssprintf("Patch copying failed:\n" "%s", sError.c_str()) ); m_State = PATCH_ERROR; } MEMCARDMAN->UnmountCard( pn ); if( m_State == PATCH_ERROR ) return; /* re-open the patch file read-open. this should not fail. */ m_PatchFile = m_MemDriver->Open( ITG_TEMP_FILE, RageFile::READ, iError ); if( !this->VerifyPatch(m_PatchFile, vsRSAPaths) ) { PATCH_TEXT( "" ); m_State = PATCH_ERROR; return; } /* reset the error checker */ iError = 0; /* check the XML data */ CString sGame, sSuccessMessage; int iPatchRevision; /* open our new copy and read from it */ RageFileDriverZip *fZip = new RageFileDriverZip( m_PatchFile ); // we'll catch this in a bit, after we've freed our memory if( !this->GetXMLData(fZip, sGame, sSuccessMessage, iPatchRevision) ) m_State = PATCH_ERROR; SAFE_DELETE( fZip ); // if the XML get earlier failed, return now. if( m_State == PATCH_ERROR ) return; // accept patches for oITG or ITG2 if( sGame != "OpenITG" && sGame != "In The Groove 2" ) { sError = ssprintf( "revision is for another game\n" "(\"%s\")", sGame.c_str() ); STATE_TEXT( ssprintf("Cannot proceed: %s", sError.c_str()) ); m_State = PATCH_ERROR; return; } int iCurrentRevision = DiagnosticsUtil::GetRevision(); // HACK: allow any patch at all if it's revision 1. if( iCurrentRevision != 1 && iCurrentRevision == iPatchRevision ) { sError = ssprintf( "patch revision (%d) matches the machine revision.", iPatchRevision ); STATE_TEXT( ssprintf("Cannot proceed: %s", sError.c_str()) ); m_State = PATCH_ERROR; return; } /* wipe any unsucessful or unused patch data */ DeleteRecursive( TEMP_PATCH_DIR ); DeleteRecursive( FINAL_PATCH_DIR ); FILEMAN->CreateDir( TEMP_PATCH_DIR ); /* re-open the ZIP file now */ fZip = new RageFileDriverZip; if( !fZip->Load(m_PatchFile) ) { PATCH_TEXT( "Failed to re-open ZIP file!" ); m_State = PATCH_ERROR; return; } CStringArray vsDirs, vsFiles; vsDirs.push_back( "/" ); /* find all the files we're going to write with a recursive check */ while( vsDirs.size() ) { CString sDir = vsDirs.back(); vsDirs.pop_back(); fZip->GetDirListing( sDir + "/*", vsFiles, false, true ); fZip->GetDirListing( sDir + "/*", vsDirs, true, true ); } PATCH_TEXT( "Extracting files..." ); /* write them now */ for( unsigned i = 0; i < vsFiles.size(); i++ ) { const CString &sPath = vsFiles[i]; CString sCleanPath = sPath; TrimLeft( sCleanPath, "/" ); if( fZip->GetFileType(sPath) != RageFileManager::TYPE_FILE ) continue; LOG->Trace( "ScreenArcadePatch: copying file \"%s\"", sCleanPath.c_str() ); PATCH_TEXT( ssprintf("Extracting files...\n" "%s", sCleanPath.c_str()) ); RageFileBasic *fCopyFrom = fZip->Open( sPath, RageFile::READ, iError ); RageFile fCopyTo; fCopyTo.Open( TEMP_PATCH_DIR + sCleanPath, RageFile::WRITE ); if( !FileCopy(*fCopyFrom, fCopyTo) ) { PATCH_TEXT( ssprintf("Could not copy \"%s\":\n" "%s", sCleanPath.c_str(),sError.c_str()) ); m_State = PATCH_ERROR; SAFE_DELETE( fCopyFrom ); SAFE_DELETE( fZip ); return; } SAFE_DELETE( fCopyFrom ); fCopyTo.Close(); /* set CHMOD info */ #ifdef LINUX /* get the actual path to the files */ CString sRealPath = ResolveTempFilePath( sCleanPath ); const RageFileDriverZip::FileInfo *fi = fZip->GetFileInfo( sPath ); int ret = chmod( sRealPath.c_str(), fi->m_iFilePermissions ); LOG->Trace( "chmod( %s, %#o ) returned %i", sRealPath.c_str(), fi->m_iFilePermissions, ret ); #endif // LINUX } SAFE_DELETE( fZip ); /* clear the previous copying text */ STATE_TEXT( "Finalizing patch data..." ); PATCH_TEXT( "" ); #ifdef LINUX sync(); sleep(5); #endif /* we've successfully copied everything. now, move the directory and we're done. */ if( FILEMAN->Move(TEMP_PATCH_DIR, FINAL_PATCH_DIR) ) { STATE_TEXT( sSuccessMessage ); m_State = PATCH_INSTALLED; } else { STATE_TEXT( "Failed to finalize patch data!\nCheck your system permissions" ); m_State = PATCH_ERROR; } }
void CSMPackageInstallDlg::OnOK() { // TODO: Add extra validation here int ProgressInit = 0; m_comboDir.EnableWindow( FALSE ); m_buttonEdit.EnableWindow( FALSE ); RString sInstallDir; { CString s; m_comboDir.GetWindowText( s ); sInstallDir = s; } // selected install dir becomes the new default int iSelectedInstallDirIndex = m_comboDir.GetCurSel(); if( iSelectedInstallDirIndex == -1 ) { Dialog::OK( NO_INSTALLATIONS.GetValue() ); return; } SMPackageUtil::SetDefaultInstallDir( iSelectedInstallDirIndex ); // mount the zip RageFileOsAbsolute file; if( !file.Open(m_sPackagePath) ) { Dialog::OK( ssprintf(COULD_NOT_OPEN_FILE.GetValue(),m_sPackagePath.c_str()) ); exit(1); // better way to abort? } RageFileDriverZip zip; if( !zip.Load(&file) ) { Dialog::OK( ssprintf(IS_NOT_A_VALID_ZIP.GetValue(),m_sPackagePath.c_str()) ); exit(1); // better way to abort? } RageFileDriverDirect dir( sInstallDir ); // handle error? // Show comment (if any) { RString sComment = zip.GetGlobalComment(); bool DontShowComment; if( sComment != "" && (!SMPackageUtil::GetPref("DontShowComment", DontShowComment) || !DontShowComment) ) { ShowComment commentDlg; commentDlg.m_sComment = sComment; int nResponse = commentDlg.DoModal(); if( nResponse != IDOK ) return; // cancelled if( commentDlg.m_bDontShow ) SMPackageUtil::SetPref( "DontShowComment", true ); } } /* Check for installed packages that should be deleted before installing. */ if( !CheckPackages(zip) ) return; // cancelled // Unzip the SMzip package into the installation folder vector<RString> vs; GetSmzipFilesToExtract( zip, vs ); for( unsigned i=0; i<vs.size(); i++ ) { // Throw some text up so the user has something to look at during the long pause. CEdit* pEdit1 = (CEdit*)GetDlgItem(IDC_STATIC_MESSAGE1); pEdit1->SetWindowText( ssprintf(INSTALLING_PLEASE_WAIT.GetValue(), m_sPackagePath.c_str()) ); CEdit* pEdit2 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE2); pEdit2->SetWindowText( "" ); GetDlgItem(IDC_STATIC_MESSAGE2)->ShowWindow( SW_HIDE ); CProgressCtrl* pProgress1 = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1); //Show the hided progress bar if(!pProgress1->IsWindowVisible()) { pProgress1->ShowWindow(SW_SHOWNORMAL); } //Initialize the progress bar and update the window 1 time (it's enough) if(!ProgressInit) { pProgress1->SetRange( 0, (short)vs.size() ); pProgress1->SetStep(1); pProgress1->SetPos(0); SendMessage( WM_PAINT ); UpdateWindow(); // Force the silly thing to hadle WM_PAINT now! ProgressInit = 1; } Dialog::Result result; do { // Extract the files const RString sFile = vs[i]; LOG->Trace( "Extracting: "+sFile ); RString sError; { int iErr; RageFileBasic *pFileFrom = zip.Open( sFile, RageFile::READ, iErr ); if( pFileFrom == NULL ) { sError = ssprintf( ERROR_OPENING_SOURCE_FILE.GetValue(), sFile.c_str(), ssprintf("%d",iErr).c_str() ); goto show_error; } int iError; RageFileBasic *pFileTo = dir.Open( sFile, RageFile::WRITE, iError ); if( pFileTo == NULL ) { sError = ssprintf( ERROR_OPENING_DESTINATION_FILE.GetValue(), sFile.c_str(), pFileTo->GetError().c_str() ); goto show_error; } RString sErr; if( !FileCopy(*pFileFrom, *pFileTo, sErr) ) { sError = ssprintf( ERROR_COPYING_FILE.GetValue(), sFile.c_str(), sErr.c_str() ); goto show_error; } SAFE_DELETE( pFileFrom ); SAFE_DELETE( pFileTo ); } break; show_error: Dialog::Result result = Dialog::AbortRetryIgnore(sError); switch( result ) { case Dialog::abort: exit(1); // better way to exit? break; case Dialog::retry: break; case Dialog::ignore: // do nothing break; } } while( result == Dialog::retry ); pProgress1->StepIt(); //increase the progress bar of 1 step } Dialog::OK( PACKAGE_INSTALLED_SUCCESSFULLY.GetValue() ); // close the dialog CDialog::OnOK(); }