// called whenever global preferences change or a file is // added or removed from gFileHistory (in order to keep // the list of recently opened documents in sync) bool Save() { // don't save preferences without the proper permission if (!HasPermission(Perm_SavePreferences)) return false; /* mark currently shown files as visible */ for (size_t i = 0; i < gWindows.Count(); i++) { UpdateCurrentFileDisplayStateForWin(gWindows.At(i)); } // remove entries which should (no longer) be remembered gFileHistory.Purge(!gGlobalPrefs->rememberStatePerDocument); // update display mode and zoom fields from internal values str::ReplacePtr(&gGlobalPrefs->defaultDisplayMode, conv::FromDisplayMode(gGlobalPrefs->defaultDisplayModeEnum)); conv::FromZoom(&gGlobalPrefs->defaultZoom, gGlobalPrefs->defaultZoomFloat); ScopedMem<WCHAR> path(GetSettingsPath()); CrashIf(!path); if (!path) return false; size_t prevPrefsDataSize; ScopedMem<char> prevPrefsData(file::ReadAll(path, &prevPrefsDataSize)); if (!gGlobalPrefs->rememberStatePerDocument || !gGlobalPrefs->rememberOpenedFiles) { for (DisplayState **ds = gGlobalPrefs->fileStates->IterStart(); ds; ds = gGlobalPrefs->fileStates->IterNext()) { (*ds)->useDefaultState = true; } // prevent unnecessary settings from being written out uint16_t fieldCount = 0; while (++fieldCount <= dimof(gFileStateFields)) { // count the number of fields up to and including useDefaultState if (gFileStateFields[fieldCount - 1].offset == offsetof(FileState, useDefaultState)) break; } // restore the correct fieldCount ASAP after serialization gFileStateInfo.fieldCount = fieldCount; } size_t prefsDataSize; ScopedMem<char> prefsData(SerializeStruct(&gGlobalPrefsInfo, gGlobalPrefs, prevPrefsData, &prefsDataSize)); if (!gGlobalPrefs->rememberStatePerDocument || !gGlobalPrefs->rememberOpenedFiles) gFileStateInfo.fieldCount = dimof(gFileStateFields); CrashIf(!prefsData || 0 == prefsDataSize); if (!prefsData || 0 == prefsDataSize) return false; // only save if anything's changed at all if (prevPrefsDataSize == prefsDataSize && str::Eq(prefsData, prevPrefsData)) return true; FileTransaction trans; bool ok = trans.WriteAll(path, prefsData, prefsDataSize) && trans.Commit(); if (!ok) return false; gGlobalPrefs->lastPrefUpdate = file::GetModificationTime(path); return true; }
bool SaveFileModifictions(const WCHAR *filePath, Vec<PageAnnotation> *list) { if (!list) return false; ScopedMem<WCHAR> modificationsPath(str::Join(filePath, SMX_FILE_EXT)); str::Str<char> data; size_t offset = 0; ScopedMem<char> prevData(file::ReadAll(modificationsPath, NULL)); Vec<PageAnnotation> *prevList = ParseFileModifications(prevData); if (prevList) { // in the case of an update, append changed annotations to the existing ones // (don't rewrite the existing ones in case they're by a newer version which // added annotation types and properties this version doesn't know anything about) for (; offset < prevList->Count() && prevList->At(offset) == list->At(offset); offset++); CrashIf(offset != prevList->Count()); data.AppendAndFree(prevData.StealData()); delete prevList; } else { data.AppendFmt("# SumatraPDF: modifications to \"%S\"\r\n", path::GetBaseName(filePath)); } data.Append("\r\n"); if (list->Count() == offset) return true; // nothing (new) to save data.AppendFmt("[@%s]\r\n", prevList ? "update" : "meta"); data.AppendFmt("version = %s\r\n", SMX_CURR_VERSION); int64 size = file::GetSize(filePath); if (0 <= size && size <= UINT_MAX) data.AppendFmt("filesize = %u\r\n", (UINT)size); SYSTEMTIME time; GetSystemTime(&time); data.AppendFmt("timestamp = %04d-%02d-%02dT%02d:%02d:%02dZ\r\n", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond); data.Append("\r\n"); for (size_t i = offset; i < list->Count(); i++) { PageAnnotation& annot = list->At(i); switch (annot.type) { case Annot_Highlight: data.Append("[highlight]\r\n"); break; case Annot_Underline: data.Append("[underline]\r\n"); break; case Annot_StrikeOut: data.Append("[strikeout]\r\n"); break; case Annot_Squiggly: data.Append("[squiggly]\r\n"); break; default: continue; } data.AppendFmt("page = %d\r\n", annot.pageNo); data.AppendFmt("rect = %g %g %g %g\r\n", annot.rect.x, annot.rect.y, annot.rect.dx, annot.rect.dy); data.AppendFmt("color = #%02x%02x%02x\r\n", annot.color.r, annot.color.g, annot.color.b); data.AppendFmt("opacity = %g\r\n", annot.color.a / 255.f); data.Append("\r\n"); } data.RemoveAt(data.Size() - 2, 2); FileTransaction trans; return trans.WriteAll(modificationsPath, data.LendData(), data.Size()) && trans.Commit(); }
bool Save(const WCHAR *filepath, SerializableGlobalPrefs& globalPrefs, FileHistory& fileHistory, Favorites* favs) { CrashIf(!filepath); if (!filepath) return false; size_t dataLen; ScopedMem<char> data(SerializePrefs(globalPrefs, fileHistory, favs, &dataLen)); if (!data) return false; assert(dataLen > 0); FileTransaction trans; bool ok = trans.WriteAll(filepath, data, dataLen) && trans.Commit(); if (ok) globalPrefs.lastPrefUpdate = file::GetModificationTime(filepath); return ok; }
bool Profile::SaveFile(const FileTransaction &transaction) { TextWriter writer(transaction.GetTemporaryPath()); // ... on error -> return if (!writer.IsOpen()) return false; KeyValueFileWriter kvwriter(writer); Export(kvwriter); return writer.Flush(); }
static bool ExtractFiles(lzma::SimpleArchive *archive) { lzma::FileInfo *fi; char *uncompressed; FileTransaction trans; for (int i = 0; gPayloadData[i].fileName; i++) { if (!gPayloadData[i].install) continue; int idx = lzma::GetIdxFromName(archive, gPayloadData[i].fileName); if (-1 == idx) { NotifyFailed(_TR("Some files to be installed are damaged or missing")); return false; } fi = &archive->files[idx]; uncompressed = lzma::GetFileDataByIdx(archive, idx, nullptr); if (!uncompressed) { NotifyFailed(_TR("The installer has been corrupted. Please download it again.\nSorry for the inconvenience!")); return false; } ScopedMem<WCHAR> filePath(str::conv::FromUtf8(fi->name)); ScopedMem<WCHAR> extPath(path::Join(gGlobalData.installDir, filePath)); bool ok = trans.WriteAll(extPath, uncompressed, fi->uncompressedSize); free(uncompressed); if (!ok) { ScopedMem<WCHAR> msg(str::Format(_TR("Couldn't write %s to disk"), filePath)); NotifyFailed(msg); return false; } trans.SetModificationTime(extPath, fi->ftModified); ProgressStep(); } return trans.Commit(); }
static bool InstallCopyFiles() { // extract all payload files one by one (transacted, if possible) ZipFile archive(GetOwnPath()); FileTransaction trans; for (int i = 0; gPayloadData[i].filepath; i++) { // skip files that are only uninstalled if (!gPayloadData[i].install) continue; ScopedMem<WCHAR> filepathT(str::conv::FromUtf8(gPayloadData[i].filepath)); size_t size; ScopedMem<char> data(archive.GetFileData(filepathT, &size)); if (!data) { NotifyFailed(L"Some files to be installed are damaged or missing"); return false; } ScopedMem<WCHAR> extpath(path::Join(gGlobalData.installDir, path::GetBaseName(filepathT))); bool ok = trans.WriteAll(extpath, data, size); if (!ok) { ScopedMem<WCHAR> msg(str::Format(L"Couldn't write %s to disk", filepathT)); NotifyFailed(msg); return false; } // set modification time to original value FILETIME ftModified = archive.GetFileTime(filepathT); trans.SetModificationTime(extpath, ftModified); ProgressStep(); } return trans.Commit(); }
inline bool Profile::SaveFile(const ProfileMap &map, const FileTransaction &transaction) { TextWriter writer(transaction.GetTemporaryPath()); // ... on error -> return if (!writer.IsOpen()) return false; KeyValueFileWriter kvwriter(writer); for (const auto &i : map) kvwriter.Write(i.first.c_str(), i.second.c_str()); return writer.Flush(); }
static bool InstallCopyFiles() { FileInfo fileInfos[32]; HRSRC resSrc = FindResource(ghinst, MAKEINTRESOURCE(1), RT_RCDATA); CrashIf(!resSrc); HGLOBAL res = LoadResource(NULL, resSrc); CrashIf(!res); const uint8_t *data = (const uint8_t*)LockResource(res); DWORD dataSize = SizeofResource(NULL, resSrc); // extract all payload files one by one (transacted, if possible) FileTransaction trans; const int32_t *idata = (const int32_t*)data; int32_t fileCount = *idata++; CrashIf(fileCount >= dimof(fileInfos)); int32_t off = 0; for (int32_t i = 0; i < fileCount; i++) { fileInfos[i].off = off; fileInfos[i].sizeUncompressed = *idata++; fileInfos[i].sizeCompressed = *idata++; off += fileInfos[i].sizeCompressed; data = (const uint8_t*)idata; fileInfos[i].name = (const char*)data; while (*data) { ++data; } ++data; idata = (const int32_t*)data; } uint8_t *dst; for (int32_t i = 0; i < fileCount; i++) { ScopedMem<WCHAR> filepathT(str::conv::FromUtf8(fileInfos[i].name)); int32_t srcLen = fileInfos[i].sizeCompressed; off = fileInfos[i].off; const uint8_t *src = data + off; unsigned dstLen; dst = decodeLZMA((uint8_t*)src, (unsigned)srcLen, &dstLen); CrashIf(dstLen != (unsigned)fileInfos[i].sizeUncompressed); ScopedMem<WCHAR> extpath(path::Join(gGlobalData.installDir, path::GetBaseName(filepathT))); bool ok = trans.WriteAll(extpath, dst, dstLen); if (!ok) { ScopedMem<WCHAR> msg(str::Format(_TR("Couldn't write %s to disk"), filepathT)); NotifyFailed(msg); goto Error; } free(dst); // set modification time to original value //FILETIME ftModified = archive.GetFileTime(filepathT); //trans.SetModificationTime(extpath, ftModified); ProgressStep(); } UnlockResource(res); return trans.Commit(); Error: UnlockResource(res); return false; }