bool Utils::deleteDir(const QString& dirPath) { QDir dir(dirPath); if (!dir.exists()) return false; dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoSymLinks); QFileInfoList infoList = dir.entryInfoList(); if (infoList.isEmpty()) return false; QFileInfoList::iterator it = infoList.begin(); QFileInfo fi; while( it != infoList.end() ) { fi = *it; if(fi.fileName() == "." || fi.fileName() == ".." ) { ++it; continue; } if( fi.isDir() ) { deleteDir(fi.absoluteFilePath()); } else if( fi.isFile() ) dir.remove(fi.absoluteFilePath()); ++it; } dir.rmdir(dir.absolutePath()); return true; }
// Function removes a directory if directory exists int rmdir() { int valid = 0; Node* current = NULL; Node* pPrev = NULL; Node* pParent = NULL; pParent = findNode(); valid = invalidPathError(pParent); if(!valid) {return 0;}; // Find dir from parent node current = pParent->childPtr; while(current != NULL && strcmp(current->name, basename) != 0) { pPrev = current; current = current->siblingPtr; } if(!current) { printf("Error: Directory does not exist\n"); return 0; } valid = invalidFileTypeError(current, 'D'); if(!valid) {return 0;} if(pParent->childPtr == current) { pParent->childPtr = current->siblingPtr; printf("Parent = %s, child = %s, sibling = %s\n", pParent->name, current->name, current->siblingPtr->name); //For testing } else { pPrev->siblingPtr = current->siblingPtr; } //Directory has been found so delete it and everything within it deleteDir(current); return 1; }
void PsUpdateDownloader::unpackUpdate() { QByteArray packed; if (!outputFile.open(QIODevice::ReadOnly)) { LOG(("Update Error: cant read updates file!")); return fatalFail(); } #ifdef Q_OS_WIN // use Lzma SDK for win const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header #else const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header #endif QByteArray compressed = outputFile.readAll(); int32 compressedLen = compressed.size() - hSize; if (compressedLen <= 0) { LOG(("Update Error: bad compressed size: %1").arg(compressed.size())); return fatalFail(); } outputFile.close(); QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyDirPath = cWorkingDir() + qsl("tupdates/ready"); deleteDir(tempDirPath); deleteDir(readyDirPath); QDir tempDir(tempDirPath), readyDir(readyDirPath); if (tempDir.exists() || readyDir.exists()) { LOG(("Update Error: cant clear tupdates/temp or tupdates/ready dir!")); return fatalFail(); } uchar sha1Buffer[20]; bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen); if (!goodSha1) { LOG(("Update Error: bad SHA1 hash of update file!")); return fatalFail(); } RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(UpdatesPublicKey), -1), 0, 0, 0); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return fatalFail(); } if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature RSA_free(pbKey); LOG(("Update Error: bad RSA signature of update file!")); return fatalFail(); } RSA_free(pbKey); QByteArray uncompressed; int32 uncompressedLen; memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen); uncompressed.resize(uncompressedLen); size_t resultLen = uncompressed.size(); #ifdef Q_OS_WIN // use Lzma SDK for win SizeT srcLen = compressedLen; int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE); if (uncompressRes != SZ_OK) { LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes)); return fatalFail(); } #else lzma_stream stream = LZMA_STREAM_INIT; lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED); if (ret != LZMA_OK) { const char *msg; switch (ret) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break; case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret)); return fatalFail(); } stream.avail_in = compressedLen; stream.next_in = (uint8_t*)(compressed.constData() + hSize); stream.avail_out = resultLen; stream.next_out = (uint8_t*)uncompressed.data(); lzma_ret res = lzma_code(&stream, LZMA_FINISH); if (stream.avail_in) { LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen)); return fatalFail(); } else if (stream.avail_out) { LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen)); return fatalFail(); } lzma_end(&stream); if (res != LZMA_OK && res != LZMA_STREAM_END) { const char *msg; switch (res) { case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break; case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break; case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break; case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break; case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break; default: msg = "Unknown error, possibly a bug"; break; } LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res)); return fatalFail(); } #endif tempDir.mkdir(tempDir.absolutePath()); quint32 version; { QBuffer buffer(&uncompressed); buffer.open(QIODevice::ReadOnly); QDataStream stream(&buffer); stream.setVersion(QDataStream::Qt_5_1); stream >> version; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (version <= AppVersion) { LOG(("Update Error: downloaded version %1 is not greater, than mine %2").arg(version).arg(AppVersion)); return fatalFail(); } quint32 filesCount; stream >> filesCount; if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read files count from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (!filesCount) { LOG(("Update Error: update is empty!")); return fatalFail(); } for (uint32 i = 0; i < filesCount; ++i) { QString relativeName; quint32 fileSize; QByteArray fileInnerData; bool executable = false; stream >> relativeName >> fileSize >> fileInnerData; #if defined Q_OS_MAC || defined Q_OS_LINUX stream >> executable; #endif if (stream.status() != QDataStream::Ok) { LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status())); return fatalFail(); } if (fileSize != quint32(fileInnerData.size())) { LOG(("Update Error: bad file size %1 not matching data size %2").arg(fileSize).arg(fileInnerData.size())); return fatalFail(); } QFile f(tempDirPath + '/' + relativeName); if (!QDir().mkpath(QFileInfo(f).absolutePath())) { LOG(("Update Error: cant mkpath for file '%1'").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } if (!f.open(QIODevice::WriteOnly)) { LOG(("Update Error: cant open file '%1' for writing").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } if (f.write(fileInnerData) != fileSize) { f.close(); LOG(("Update Error: cant write file '%1'").arg(tempDirPath + '/' + relativeName)); return fatalFail(); } f.close(); if (executable) { QFileDevice::Permissions p = f.permissions(); p |= QFileDevice::ExeOwner | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther; f.setPermissions(p); } } // create tdata/version file tempDir.mkdir(QDir(tempDirPath + qsl("/tdata")).absolutePath()); std::wstring versionString = ((version % 1000) ? QString("%1.%2.%3").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000)).arg(int(version % 1000)) : QString("%1.%2").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000))).toStdWString(); VerInt versionNum = VerInt(version), versionLen = VerInt(versionString.size() * sizeof(VerChar)); VerChar versionStr[32]; memcpy(versionStr, versionString.c_str(), versionLen); QFile fVersion(tempDirPath + qsl("/tdata/version")); if (!fVersion.open(QIODevice::WriteOnly)) { LOG(("Update Error: cant write version file '%1'").arg(tempDirPath + qsl("/version"))); return fatalFail(); } fVersion.write((const char*)&versionNum, sizeof(VerInt)); fVersion.write((const char*)&versionLen, sizeof(VerInt)); fVersion.write((const char*)&versionStr[0], versionLen); fVersion.close(); } if (!tempDir.rename(tempDir.absolutePath(), readyDir.absolutePath())) { LOG(("Update Error: cant rename temp dir '%1' to ready dir '%2'").arg(tempDir.absolutePath()).arg(readyDir.absolutePath())); return fatalFail(); } deleteDir(tempDirPath); outputFile.remove(); emit App::app()->updateReady(); }
void PsUpdateDownloader::clearAll() { deleteDir(cWorkingDir() + qsl("tupdates")); }
foreach (QString dirPath, sTempDirToCleanUp) { qWarning() << "will delete" << dirPath; deleteDir(dirPath); }
Desktopwidget::Desktopwidget (QWidget *parent) : QSplitter (parent) { _model = new Dirmodel (); // _model->setLazyChildCount (true); _dir = new Dirview (this); _dir->setModel (_model); _contents = new Desktopmodel (this); QWidget *group = createToolbar(); _view = new Desktopview (group); QVBoxLayout *lay = new QVBoxLayout (group); lay->setContentsMargins (0, 0, 0, 0); lay->setSpacing (2); lay->addWidget (_toolbar); lay->addWidget (_view); connect (_view, SIGNAL (itemPreview (const QModelIndex &, int, bool)), this, SLOT (slotItemPreview (const QModelIndex &, int, bool))); #ifdef USE_PROXY _proxy = new Desktopproxy (this); _proxy->setSourceModel (_contents); _view->setModel (_proxy); // printf ("contents=%p, proxy=%p\n", _contents, _proxy); // set up the model converter _modelconv = new Desktopmodelconv (_contents, _proxy); // setup another one for Desktopmodel, which only allows assertions _modelconv_assert = new Desktopmodelconv (_contents, _proxy, false); #else _proxy = 0; _view->setModel (_contents); _modelconv = new Desktopmodelconv (_contents); // setup another one for Desktopmodel, which only allows assertions _modelconv_assert = new Desktopmodelconv (_contents, false); #endif _view->setModelConv (_modelconv); _contents->setModelConv (_modelconv_assert); _delegate = new Desktopdelegate (_modelconv, this); _view->setItemDelegate (_delegate); connect (_delegate, SIGNAL (itemClicked (const QModelIndex &, int)), this, SLOT (slotItemClicked (const QModelIndex &, int))); connect (_delegate, SIGNAL (itemPreview (const QModelIndex &, int, bool)), this, SLOT (slotItemPreview (const QModelIndex &, int, bool))); connect (_delegate, SIGNAL (itemDoubleClicked (const QModelIndex &)), this, SLOT (openStack (const QModelIndex &))); connect (_contents, SIGNAL (undoChanged ()), this, SIGNAL (undoChanged ())); connect (_contents, SIGNAL (dirChanged (QString&, QModelIndex&)), this, SLOT (slotDirChanged (QString&, QModelIndex&))); connect (_contents, SIGNAL (beginningScan (const QModelIndex &)), this, SLOT (slotBeginningScan (const QModelIndex &))); connect (_contents, SIGNAL (endingScan (bool)), this, SLOT (slotEndingScan (bool))); connect (_contents, SIGNAL(updateRepositoryList (QString &, bool)), this, SLOT(slotUpdateRepositoryList (QString &, bool))); // position the items when the model is reset, otherwise things // move and look ugly for a while connect (_contents, SIGNAL (modelReset ()), _view, SLOT (setPositions ())); createPage(); // and when there are no selected items connect (_view, SIGNAL (pageLost()), _page, SLOT (slotReset ())); _parent = parent; _pendingMatch = QString::null; _updating = false; // setup the preview timer _timer = new QTimer (); _timer->setSingleShot (true); connect (_timer, SIGNAL(timeout()), this, SLOT(updatePreview())); connect (_dir, SIGNAL (clicked (const QModelIndex&)), this, SLOT (dirSelected (const QModelIndex&))); connect (_dir, SIGNAL (activated (const QModelIndex&)), this, SLOT (dirSelected (const QModelIndex&))); connect (_model, SIGNAL(droppedOnFolder(const QMimeData *, QString &)), this, SLOT(slotDroppedOnFolder(const QMimeData *, QString &))); /* notice when the current directory is fully displayed so we can handle any pending action */ connect (_contents, SIGNAL (updateDone()), this, SLOT (slotUpdateDone())); // connect signals from the directory tree connect (_dir->_new, SIGNAL (triggered ()), this, SLOT (newDir ())); connect (_dir->_rename, SIGNAL (triggered ()), this, SLOT (renameDir ())); connect (_dir->_delete, SIGNAL (triggered ()), this, SLOT (deleteDir ())); connect (_dir->_refresh, SIGNAL (triggered ()), this, SLOT (refreshDir ())); connect (_dir->_add_recent, SIGNAL (triggered ()), this, SLOT (addToRecent ())); connect (_dir->_add_repository, SIGNAL (triggered ()), this, SLOT (slotAddRepository ())); connect (_dir->_remove_repository, SIGNAL (triggered ()), this, SLOT (slotRemoveRepository ())); setStretchFactor(indexOf(_dir), 0); QList<int> size; if (!getSettingsSizes ("desktopwidget/", size)) { size.append (200); size.append (1000); size.append (400); } setSizes (size); connect (_view, SIGNAL (popupMenu (QModelIndex &)), this, SLOT (slotPopupMenu (QModelIndex &))); // allow top level to see our view messages connect (_view, SIGNAL (newContents (QString)), this, SIGNAL (newContents (QString))); addActions(); /* unfortunately when we first run maxview it starts with the main window un-maximised. This means that scrollToLast() doesn't quite scroll far enough for the maximised view which appears soon afterwards. As a hack for the moment, we do another scroll 1 second after starting up */ QTimer::singleShot(1000, _view, SLOT (scrollToLast())); }
bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { if (installInProgress_) { ERROR_LOG(HLE, "Cannot have two installs in progress at the same time"); return false; } installInProgress_ = true; std::string pspGame = GetSysDirectory(DIRECTORY_GAME); INFO_LOG(HLE, "Installing %s into %s", zipfile.c_str(), pspGame.c_str()); if (!File::Exists(zipfile)) { ERROR_LOG(HLE, "ZIP file %s doesn't exist", zipfile.c_str()); return false; } int error; #if defined(_WIN32) && !defined(__MINGW32__) struct zip *z = zip_open(ConvertUTF8ToWString(zipfile).c_str(), 0, &error); #elif defined(__SYMBIAN32__) // If zipfile is non-ascii, this may not function correctly. Other options? struct zip *z = zip_open(std::wstring(zipfile.begin(), zipfile.end()).c_str(), 0, &error); #else struct zip *z = zip_open(zipfile.c_str(), 0, &error); #endif if (!z) { ERROR_LOG(HLE, "Failed to open ZIP file %s, error code=%i", zipfile.c_str(), error); return false; } int numFiles = zip_get_num_files(z); // First, find all the directories, and precreate them before we fill in with files. // Also, verify that this is a PSP zip file with the correct layout. bool isPSP = false; int stripChars = 0; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); std::string zippedName = fn; if (zippedName.find("EBOOT.PBP") != std::string::npos) { int slashCount = 0; int lastSlashLocation = -1; int slashLocation = -1; for (size_t i = 0; i < zippedName.size(); i++) { if (zippedName[i] == '/') { slashCount++; slashLocation = lastSlashLocation; lastSlashLocation = (int)i; } } if (slashCount >= 1 && (!isPSP || slashLocation < stripChars + 1)) { stripChars = slashLocation + 1; isPSP = true; } else { INFO_LOG(HLE, "Wrong number of slashes (%i) in %s", slashCount, zippedName.c_str()); } } } if (!isPSP) { ERROR_LOG(HLE, "File not a PSP game, no EBOOT.PBP found."); installProgress_ = 0.0f; installInProgress_ = false; installError_ = "Not a PSP game"; InstallDone(); return false; } size_t allBytes = 0, bytesCopied = 0; // Create all the directories in one pass std::set<std::string> createdDirs; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); std::string zippedName = fn; std::string outFilename = pspGame + zippedName.substr(stripChars); bool isDir = *outFilename.rbegin() == '/'; if (!isDir && outFilename.find("/") != std::string::npos) { outFilename = outFilename.substr(0, outFilename.rfind('/')); } if (createdDirs.find(outFilename) == createdDirs.end()) { File::CreateFullPath(outFilename.c_str()); createdDirs.insert(outFilename); } if (!isDir && strchr(fn, '/') != 0) { struct zip_stat zstat; if (zip_stat_index(z, i, 0, &zstat) >= 0) { allBytes += zstat.size; } } } // Now, loop through again in a second pass, writing files. std::vector<std::string> createdFiles; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); // Note that we do NOT write files that are not in a directory, to avoid random // README files etc. if (strchr(fn, '/') != 0) { struct zip_stat zstat; zip_stat_index(z, i, 0, &zstat); size_t size = zstat.size; fn += stripChars; std::string outFilename = pspGame + fn; bool isDir = *outFilename.rbegin() == '/'; if (isDir) continue; if (i < 10) { INFO_LOG(HLE, "Writing %i bytes to %s", (int)size, outFilename.c_str()); } zip_file *zf = zip_fopen_index(z, i, 0); FILE *f = fopen(outFilename.c_str(), "wb"); if (f) { size_t pos = 0; const size_t blockSize = 1024 * 128; u8 *buffer = new u8[blockSize]; while (pos < size) { size_t bs = std::min(blockSize, pos - size); zip_fread(zf, buffer, bs); size_t written = fwrite(buffer, 1, bs, f); if (written != bs) { ERROR_LOG(HLE, "Wrote %i bytes out of %i - Disk full?", (int)written, (int)bs); delete [] buffer; buffer = 0; fclose(f); zip_fclose(zf); deleteFile(outFilename.c_str()); // Yes it's a goto. Sue me. I think it's appropriate here. goto bail; } pos += bs; bytesCopied += bs; installProgress_ = (float)bytesCopied / (float)allBytes; // printf("Progress: %f\n", installProgress_); } zip_fclose(zf); fclose(f); createdFiles.push_back(outFilename); delete [] buffer; } else { ERROR_LOG(HLE, "Failed to open file for writing"); } } } INFO_LOG(HLE, "Extracted %i files (%i bytes / %i).", numFiles, (int)bytesCopied, (int)allBytes); zip_close(z); z = 0; installProgress_ = 1.0f; installInProgress_ = false; installError_ = ""; if (deleteAfter) { deleteFile(zipfile.c_str()); } InstallDone(); return true; bail: zip_close(z); // We end up here if disk is full or couldn't write to storage for some other reason. installProgress_ = 0.0f; installInProgress_ = false; installError_ = "Storage full"; if (deleteAfter) { deleteFile(zipfile.c_str()); } for (size_t i = 0; i < createdFiles.size(); i++) { deleteFile(createdFiles[i].c_str()); } for (auto iter = createdDirs.begin(); iter != createdDirs.end(); ++iter) { deleteDir(iter->c_str()); } InstallDone(); return false; }
int IPC_deleteDir(const int year, const int month, const int day) { char prefix[1024] = {0}; (void)snprintf(prefix, sizeof(prefix), "%s/%d/%d/%d/", __ystNum, year, month, day); return deleteDir(__bucket, prefix); }
int main(int argc, char *argv[]) //Connecting to Server (SOCKET) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; if (argc < 3) { fprintf(stderr,"usage %s hostname port\n", argv[0]); exit(0); } portno = atoi(argv[2]); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); server = gethostbyname(argv[1]); if (server == NULL) { fprintf(stderr,"ERROR, no such host\n"); exit(0); } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting"); printf("\n~~~~~ File Repository System ~~~~~"); int count = 0; while(count == 0){ //Getting Client's choice //printf("\n\n1.Create 2.Download 3.Send 4.Delete 5.Exit : "); printf("\n\nFile: 1.Send 2.Download 3.Create 4.Delete"); printf("\nDirectory: 5.Create 6.Delete 7.Copy 8.Exit : "); char buffer[256]; printf("\nPlease insert your choice: "); bzero(buffer,256); fgets(buffer,255,stdin); char input[256]; strcpy(input, buffer); //Sending Client's choice to Server int datalen = strlen(buffer); int tmp = htonl(datalen); n = write(sockfd, (char*)&tmp, sizeof(tmp)); if(n < 0) error("ERROR writing to socket"); n = write(sockfd,buffer,datalen); if (n < 0) error("ERROR writing to socket"); if((strcmp(input, "1\n")) == 0){ //Client send file to Server sendFile(sockfd); count = 0; } else if((strcmp(input, "2\n")) == 0){ //Client download file from Server downloadFile(sockfd); count = 0; } else if((strcmp(input, "3\n")) == 0){ //Client create file to Server createFile(sockfd); count = 1; } else if((strcmp(input, "4\n")) == 0){ //Client delete file to Server deleteFile(sockfd); count = 1; } else if((strcmp(input, "5\n")) == 0){ //Create directory on client-site //createFile(sockfd); createDir(sockfd); count = 1; } else if((strcmp(input, "6\n")) == 0){ //Delete directory on client-site deleteDir(sockfd); count = 1; } else if((strcmp(input, "7\n")) == 0){ //Copy directory on client-site copyDir(sockfd); count = 1; } else if((strcmp(input, "8\n")) == 0){ //Client disconnect from Server count++; } else{ printf("\nWrong input, please try again."); //Invalid input from Client count = 0; } } close(sockfd); printf("\n~~ Process End.\n~~ Disconnected from the Server.\n\n"); return 0; }
void deleteDirOrDie(char *dirname) { if(!deleteDir(dirname)) { exit(10); } }
mitk::DataStorage::Pointer mitk::SceneIO::LoadScene( const std::string& filename, DataStorage* pStorage, bool clearStorageFirst ) { // prepare data storage DataStorage::Pointer storage = pStorage; if ( storage.IsNull() ) { storage = StandaloneDataStorage::New().GetPointer(); } if ( clearStorageFirst ) { try { storage->Remove( storage->GetAll() ); } catch(...) { MITK_ERROR << "DataStorage cannot be cleared properly."; } } // test input filename if ( filename.empty() ) { MITK_ERROR << "No filename given. Not possible to load scene."; return NULL; } // test if filename can be read std::ifstream file( filename.c_str(), std::ios::binary ); if (!file.good()) { MITK_ERROR << "Cannot open '" << filename << "' for reading"; return NULL; } // get new temporary directory m_WorkingDirectory = CreateEmptyTempDirectory(); if (m_WorkingDirectory.empty()) { MITK_ERROR << "Could not create temporary directory. Cannot open scene files."; return NULL; } // unzip all filenames contents to temp dir m_UnzipErrors = 0; Poco::Zip::Decompress unzipper( file, Poco::Path( m_WorkingDirectory ) ); unzipper.EError += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string> >(this, &SceneIO::OnUnzipError); unzipper.EOk += Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path> >(this, &SceneIO::OnUnzipOk); unzipper.decompressAllFiles(); unzipper.EError -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string> >(this, &SceneIO::OnUnzipError); unzipper.EOk -= Poco::Delegate<SceneIO, std::pair<const Poco::Zip::ZipLocalFileHeader, const Poco::Path> >(this, &SceneIO::OnUnzipOk); if ( m_UnzipErrors ) { MITK_ERROR << "There were " << m_UnzipErrors << " errors unzipping '" << filename << "'. Will attempt to read whatever could be unzipped."; } // test if index.xml exists // parse index.xml with TinyXML TiXmlDocument document( m_WorkingDirectory + Poco::Path::separator() + "index.xml" ); if (!document.LoadFile()) { MITK_ERROR << "Could not open/read/parse " << m_WorkingDirectory << "/index.xml\nTinyXML reports: " << document.ErrorDesc() << std::endl; return NULL; } SceneReader::Pointer reader = SceneReader::New(); if ( !reader->LoadScene( document, m_WorkingDirectory, storage ) ) { MITK_ERROR << "There were errors while loading scene file " << filename << ". Your data may be corrupted"; } // delete temp directory try { Poco::File deleteDir( m_WorkingDirectory ); deleteDir.remove(true); // recursive } catch(...) { MITK_ERROR << "Could not delete temporary directory " << m_WorkingDirectory; } // return new data storage, even if empty or uncomplete (return as much as possible but notify calling method) return storage; }
bool mitk::SceneIO::SaveScene( DataStorage::SetOfObjects::ConstPointer sceneNodes, const DataStorage* storage, const std::string& filename) { if (!sceneNodes) { MITK_ERROR << "No set of nodes given. Not possible to save scene."; return false; } if (!storage) { MITK_ERROR << "No data storage given. Not possible to save scene."; // \TODO: Technically, it would be possible to save the nodes without their relation return false; } if ( filename.empty() ) { MITK_ERROR << "No filename given. Not possible to save scene."; return false; } try { m_FailedNodes = DataStorage::SetOfObjects::New(); m_FailedProperties = PropertyList::New(); // start XML DOM TiXmlDocument document; TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "UTF-8", "" ); // TODO what to write here? encoding? standalone would mean that we provide a DTD somewhere... document.LinkEndChild( decl ); TiXmlElement* version = new TiXmlElement("Version"); version->SetAttribute("Writer", __FILE__ ); version->SetAttribute("Revision", "$Revision: 17055 $" ); version->SetAttribute("FileVersion", 1 ); document.LinkEndChild(version); //DataStorage::SetOfObjects::ConstPointer sceneNodes = storage->GetSubset( predicate ); if ( sceneNodes.IsNull() ) { MITK_WARN << "Saving empty scene to " << filename; } else { if ( sceneNodes->size() == 0 ) { MITK_WARN << "Saving empty scene to " << filename; } MITK_INFO << "Storing scene with " << sceneNodes->size() << " objects to " << filename; m_WorkingDirectory = CreateEmptyTempDirectory(); if (m_WorkingDirectory.empty()) { MITK_ERROR << "Could not create temporary directory. Cannot create scene files."; return false; } ProgressBar::GetInstance()->AddStepsToDo( sceneNodes->size() ); // find out about dependencies typedef std::map< DataNode*, std::string > UIDMapType; typedef std::map< DataNode*, std::list<std::string> > SourcesMapType; UIDMapType nodeUIDs; // for dependencies: ID of each node SourcesMapType sourceUIDs; // for dependencies: IDs of a node's parent nodes UIDGenerator nodeUIDGen("OBJECT_"); for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter) { DataNode* node = iter->GetPointer(); if (!node) continue; // unlikely event that we get a NULL pointer as an object for saving. just ignore // generate UIDs for all source objects DataStorage::SetOfObjects::ConstPointer sourceObjects = storage->GetSources( node ); for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = sourceObjects->begin(); sourceIter != sourceObjects->end(); ++sourceIter ) { if ( std::find( sceneNodes->begin(), sceneNodes->end(), *sourceIter ) == sceneNodes->end() ) continue; // source is not saved, so don't generate a UID for this source // create a uid for the parent object if ( nodeUIDs[ *sourceIter ].empty() ) { nodeUIDs[ *sourceIter ] = nodeUIDGen.GetUID(); } // store this dependency for writing sourceUIDs[ node ].push_back( nodeUIDs[*sourceIter] ); } if ( nodeUIDs[ node ].empty() ) { nodeUIDs[ node ] = nodeUIDGen.GetUID(); } } // write out objects, dependencies and properties for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); iter != sceneNodes->end(); ++iter) { DataNode* node = iter->GetPointer(); if (node) { TiXmlElement* nodeElement = new TiXmlElement("node"); std::string filenameHint( node->GetName() ); filenameHint = itksys::SystemTools::MakeCindentifier(filenameHint.c_str()); // escape filename <-- only allow [A-Za-z0-9_], replace everything else with _ // store dependencies UIDMapType::iterator searchUIDIter = nodeUIDs.find(node); if ( searchUIDIter != nodeUIDs.end() ) { // store this node's ID nodeElement->SetAttribute("UID", searchUIDIter->second.c_str() ); } SourcesMapType::iterator searchSourcesIter = sourceUIDs.find(node); if ( searchSourcesIter != sourceUIDs.end() ) { // store all source IDs for ( std::list<std::string>::iterator sourceUIDIter = searchSourcesIter->second.begin(); sourceUIDIter != searchSourcesIter->second.end(); ++sourceUIDIter ) { TiXmlElement* uidElement = new TiXmlElement("source"); uidElement->SetAttribute("UID", sourceUIDIter->c_str() ); nodeElement->LinkEndChild( uidElement ); } } // store basedata if ( BaseData* data = node->GetData() ) { //std::string filenameHint( node->GetName() ); bool error(false); TiXmlElement* dataElement( SaveBaseData( data, filenameHint, error ) ); // returns a reference to a file if (error) { m_FailedNodes->push_back( node ); } // store basedata properties PropertyList* propertyList = data->GetPropertyList(); if (propertyList && !propertyList->IsEmpty() ) { TiXmlElement* baseDataPropertiesElement( SavePropertyList( propertyList, filenameHint + "-data") ); // returns a reference to a file dataElement->LinkEndChild( baseDataPropertiesElement ); } nodeElement->LinkEndChild( dataElement ); } // store all renderwindow specific propertylists const RenderingManager::RenderWindowVector& allRenderWindows( RenderingManager::GetInstance()->GetAllRegisteredRenderWindows() ); for ( RenderingManager::RenderWindowVector::const_iterator rw = allRenderWindows.begin(); rw != allRenderWindows.end(); ++rw) { if (vtkRenderWindow* renderWindow = *rw) { std::string renderWindowName( mitk::BaseRenderer::GetInstance(renderWindow)->GetName() ); BaseRenderer* renderer = mitk::BaseRenderer::GetInstance(renderWindow); PropertyList* propertyList = node->GetPropertyList(renderer); if ( propertyList && !propertyList->IsEmpty() ) { TiXmlElement* renderWindowPropertiesElement( SavePropertyList( propertyList, filenameHint + "-" + renderWindowName) ); // returns a reference to a file renderWindowPropertiesElement->SetAttribute("renderwindow", renderWindowName); nodeElement->LinkEndChild( renderWindowPropertiesElement ); } } } // don't forget the renderwindow independent list PropertyList* propertyList = node->GetPropertyList(); if ( propertyList && !propertyList->IsEmpty() ) { TiXmlElement* propertiesElement( SavePropertyList( propertyList, filenameHint + "-node") ); // returns a reference to a file nodeElement->LinkEndChild( propertiesElement ); } document.LinkEndChild( nodeElement ); } else { MITK_WARN << "Ignoring NULL node during scene serialization."; } ProgressBar::GetInstance()->Progress(); } // end for all nodes } // end if sceneNodes if ( !document.SaveFile( m_WorkingDirectory + Poco::Path::separator() + "index.xml" ) ) { MITK_ERROR << "Could not write scene to " << m_WorkingDirectory << Poco::Path::separator() << "index.xml" << "\nTinyXML reports '" << document.ErrorDesc() << "'"; return false; } else { try { Poco::File deleteFile( filename.c_str() ); if (deleteFile.exists()) { deleteFile.remove(); } // create zip at filename std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out); if (!file.good()) { MITK_ERROR << "Could not open a zip file for writing: '" << filename << "'"; } else { Poco::Zip::Compress zipper( file, true ); Poco::Path tmpdir( m_WorkingDirectory ); zipper.addRecursive( tmpdir ); zipper.close(); } try { Poco::File deleteDir( m_WorkingDirectory ); deleteDir.remove(true); // recursive } catch(...) { MITK_ERROR << "Could not delete temporary directory " << m_WorkingDirectory; return false; // ok? } } catch(std::exception& e) { MITK_ERROR << "Could not create ZIP file from " << m_WorkingDirectory << "\nReason: " << e.what(); return false; } return true; } } catch(std::exception& e) { MITK_ERROR << "Caught exception during saving temporary files to disk. Error description: '" << e.what() << "'"; return false; } }