CString FileSystem::MakeExtendedPath(const char* path, bool force) { #ifdef WIN32 if (force || NeedLongPath(path)) { CString canonicalPath = MakeCanonicalPath(path); BString<1024> longpath; if (canonicalPath[0] == '\\' && canonicalPath[1] == '\\') { // UNC path longpath.Format("\\\\?\\UNC\\%s", canonicalPath + 2); } else { // local path longpath.Format("\\\\?\\%s", canonicalPath); } return *longpath; } else #endif { return path; } }
void Log::RotateLog() { BString<1024> directory = g_Options->GetLogFile(); // split the full filename into path, basename and extension char* baseName = FileSystem::BaseFileName(directory); if (baseName > directory) { baseName[-1] = '\0'; } BString<1024> baseExt; char* ext = strrchr(baseName, '.'); if (ext && ext > baseName) { baseExt = ext; ext[0] = '\0'; } BString<1024> fileMask("%s-####-##-##%s", baseName, *baseExt); time_t curTime = Util::CurrentTime() + g_Options->GetTimeCorrection(); int curDay = (int)curTime / 86400; BString<1024> fullFilename; WildMask mask(fileMask, true); DirBrowser dir(directory); while (const char* filename = dir.Next()) { if (mask.Match(filename)) { fullFilename.Format("%s%c%s", *directory, PATH_SEPARATOR, filename); struct tm tm; memset(&tm, 0, sizeof(tm)); tm.tm_year = atoi(filename + mask.GetMatchStart(0)) - 1900; tm.tm_mon = atoi(filename + mask.GetMatchStart(1)) - 1; tm.tm_mday = atoi(filename + mask.GetMatchStart(2)); time_t fileTime = Util::Timegm(&tm); int fileDay = (int)fileTime / 86400; if (fileDay <= curDay - g_Options->GetRotateLog()) { BString<1024> message("Deleting old log-file %s\n", filename); g_Log->AddMessage(Message::mkInfo, message); FileSystem::DeleteFile(fullFilename); } } } struct tm tm; gmtime_r(&curTime, &tm); fullFilename.Format("%s%c%s-%i-%.2i-%.2i%s", *directory, PATH_SEPARATOR, baseName, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, *baseExt); m_logFilename = fullFilename; }
void NCursesFrontend::PrintTopHeader(char* header, int lineNr, bool upTime) { BString<1024> buffer("%-*s", m_screenWidth, header); int headerLen = strlen(header); int charsLeft = m_screenWidth - headerLen - 2; int time = upTime ? m_upTimeSec : m_dnTimeSec; int d = time / 3600 / 24; int h = (time % (3600 * 24)) / 3600; int m = (time % 3600) / 60; int s = time % 60; BString<100> timeStr; if (d == 0) { timeStr.Format("%.2d:%.2d:%.2d", h, m, s); if ((int)strlen(timeStr) > charsLeft) { timeStr.Format("%.2d:%.2d", h, m); } } else { timeStr.Format("%i %s %.2d:%.2d:%.2d", d, (d == 1 ? "day" : "days"), h, m, s); if ((int)strlen(timeStr) > charsLeft) { timeStr.Format("%id %.2d:%.2d:%.2d", d, h, m, s); } if ((int)strlen(timeStr) > charsLeft) { timeStr.Format("%id %.2d:%.2d", d, h, m); } } const char* shortCap = upTime ? " Up " : "Dn "; const char* longCap = upTime ? " Uptime " : " Download-time "; int timeLen = strlen(timeStr); int shortCapLen = strlen(shortCap); int longCapLen = strlen(longCap); if (charsLeft - timeLen - longCapLen >= 0) { snprintf(buffer + m_screenWidth - timeLen - longCapLen, MAX_SCREEN_WIDTH - (m_screenWidth - timeLen - longCapLen), "%s%s", longCap, *timeStr); } else if (charsLeft - timeLen - shortCapLen >= 0) { snprintf(buffer + m_screenWidth - timeLen - shortCapLen, MAX_SCREEN_WIDTH - (m_screenWidth - timeLen - shortCapLen), "%s%s", shortCap, *timeStr); } else if (charsLeft - timeLen >= 0) { snprintf(buffer + m_screenWidth - timeLen, MAX_SCREEN_WIDTH - (m_screenWidth - timeLen), "%s", *timeStr); } PlotLine(buffer, lineNr, 0, NCURSES_COLORPAIR_INFOLINE); }
void NCursesFrontend::PrintFilename(FileInfo * fileInfo, int row, bool selected) { int color = 0; const char* Brace1 = "["; const char* Brace2 = "]"; if (m_inputMode == editQueue && selected) { color = NCURSES_COLORPAIR_TEXTHIGHL; if (!m_useColor) { Brace1 = "<"; Brace2 = ">"; } } else { color = NCURSES_COLORPAIR_TEXT; } const char* downloading = ""; if (fileInfo->GetActiveDownloads() > 0) { downloading = " *"; } BString<100> priority; if (fileInfo->GetNzbInfo()->GetPriority() != 0) { priority.Format(" [%+i]", fileInfo->GetNzbInfo()->GetPriority()); } BString<100> completed; if (fileInfo->GetRemainingSize() < fileInfo->GetSize()) { completed.Format(", %i%%", (int)(100 - fileInfo->GetRemainingSize() * 100 / fileInfo->GetSize())); } BString<1024> nzbNiceName; if (m_showNzbname) { nzbNiceName.Format("%s%c", fileInfo->GetNzbInfo()->GetName(), PATH_SEPARATOR); } BString<1024> text("%s%i%s%s%s %s%s (%s%s)%s", Brace1, fileInfo->GetId(), Brace2, *priority, downloading, *nzbNiceName, fileInfo->GetFilename(), *Util::FormatSize(fileInfo->GetSize()), *completed, fileInfo->GetPaused() ? " (paused)" : ""); PlotLine(text, row, 0, color); }
void WebProcessor::SendBodyResponse(const char* body, int bodyLen, const char* contentType) { const char* RESPONSE_HEADER = "HTTP/1.1 200 OK\r\n" "Connection: close\r\n" "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n" "Access-Control-Allow-Origin: %s\r\n" "Access-Control-Allow-Credentials: true\r\n" "Access-Control-Max-Age: 86400\r\n" "Access-Control-Allow-Headers: Content-Type, Authorization\r\n" "X-Auth-Token: %s\r\n" "Content-Length: %i\r\n" "%s" // Content-Type: xxx "%s" // Content-Encoding: gzip "Server: nzbget-%s\r\n" "\r\n"; #ifndef DISABLE_GZIP CharBuffer gbuf; bool gzip = m_gzip && bodyLen > MAX_UNCOMPRESSED_SIZE; if (gzip) { uint32 outLen = ZLib::GZipLen(bodyLen); gbuf.Reserve(outLen); int gzippedLen = ZLib::GZip(body, bodyLen, *gbuf, outLen); if (gzippedLen > 0 && gzippedLen < bodyLen) { body = gbuf; bodyLen = gzippedLen; } else { gzip = false; } } #else bool gzip = false; #endif BString<1024> contentTypeHeader; if (contentType) { contentTypeHeader.Format("Content-Type: %s\r\n", contentType); } BString<1024> responseHeader(RESPONSE_HEADER, m_origin.Str(), m_serverAuthToken[m_userAccess], bodyLen, *contentTypeHeader, gzip ? "Content-Encoding: gzip\r\n" : "", Util::VersionRevision()); // Send the request answer m_connection->Send(responseHeader, responseHeader.Length()); m_connection->Send(body, bodyLen); }
void ParRenamer::RenameParFile(const char* destDir, const char* filename, const char* setId) { debug("Renaming: %s; setid: %s", FileSystem::BaseFileName(filename), setId); BString<1024> destFileName; int num = 1; while (num == 1 || FileSystem::FileExists(destFileName)) { destFileName.Format("%s%c%s.vol%03i+01.PAR2", destDir, PATH_SEPARATOR, setId, num); num++; } RenameFile(filename, destFileName); }
void WinConsole::ShowCategoryDir(int catIndex) { Options::Category& category = g_Options->GetCategories()->at(catIndex); BString<1024> destDir = category.GetDestDir(); if (destDir.Empty()) { CString categoryDir = FileSystem::MakeValidFilename(category.GetName(), true); destDir.Format("%s%c%s", g_Options->GetDestDir(), PATH_SEPARATOR, *categoryDir); } ShowInExplorer(destDir); }
void NCursesFrontend::PrintStatus() { int statusRow = m_screenHeight - 2; BString<100> timeString; int currentDownloadSpeed = m_standBy ? 0 : m_currentDownloadSpeed; if (currentDownloadSpeed > 0 && !m_pauseDownload) { int64 remain_sec = (int64)(m_remainingSize / currentDownloadSpeed); int h = (int)(remain_sec / 3600); int m = (int)((remain_sec % 3600) / 60); int s = (int)(remain_sec % 60); timeString.Format(" (~ %.2d:%.2d:%.2d)", h, m, s); } BString<100> downloadLimit; if (m_downloadLimit > 0) { downloadLimit.Format(", Limit %i KB/s", m_downloadLimit / 1024); } BString<100> postStatus; if (m_postJobCount > 0) { postStatus.Format(", %i post-job%s", m_postJobCount, m_postJobCount > 1 ? "s" : ""); } int averageSpeed = (int)(m_dnTimeSec > 0 ? m_allBytes / m_dnTimeSec : 0); BString<1024> status(" %d threads, %s, %s remaining%s%s%s%s, Avg. %s", m_threadCount, *Util::FormatSpeed(currentDownloadSpeed), *Util::FormatSize(m_remainingSize), *timeString, *postStatus, m_pauseDownload ? (m_standBy ? ", Paused" : ", Pausing") : "", *downloadLimit, *Util::FormatSpeed(averageSpeed)); PlotLine(status, statusRow, 0, NCURSES_COLORPAIR_STATUS); }
bool ArticleCache::CheckFlush(bool flushEverything) { debug("Checking cache, Allocated: %i, FlushEverything: %i", (int)m_allocated, (int)flushEverything); BString<1024> infoName; { GuardedDownloadQueue downloadQueue = DownloadQueue::Guard(); for (NzbInfo* nzbInfo : downloadQueue->GetQueue()) { if (m_fileInfo) { break; } for (FileInfo* fileInfo : nzbInfo->GetFileList()) { if (fileInfo->GetCachedArticles() > 0 && (fileInfo->GetActiveDownloads() == 0 || flushEverything)) { m_fileInfo = fileInfo; infoName.Format("%s%c%s", m_fileInfo->GetNzbInfo()->GetName(), PATH_SEPARATOR, m_fileInfo->GetFilename()); break; } } } } if (m_fileInfo) { ArticleWriter articleWriter; articleWriter.SetFileInfo(m_fileInfo); articleWriter.SetInfoName(infoName); articleWriter.FlushCache(); m_fileInfo = nullptr; return true; } debug("Checking cache... nothing to flush"); return false; }
void NCursesFrontend::PrintGroupname(NzbInfo* nzbInfo, int row, bool selected, bool calcColWidth) { int color = NCURSES_COLORPAIR_TEXT; char chBrace1 = '['; char chBrace2 = ']'; if (m_inputMode == editQueue && selected) { color = NCURSES_COLORPAIR_TEXTHIGHL; if (!m_useColor) { chBrace1 = '<'; chBrace2 = '>'; } } const char* downloading = ""; if (nzbInfo->GetActiveDownloads() > 0) { downloading = " *"; } BString<100> priority; if (nzbInfo->GetPriority() != 0) { priority.Format(" [%+i]", nzbInfo->GetPriority()); } // Format: // [id - id] Name Left-Files/Paused Total Left Time // [1-2] Nzb-name 999/999 999.99 MB 999.99 MB 00:00:00 int nameLen = 0; if (calcColWidth) { nameLen = m_screenWidth - 1 - 9 - 11 - 11 - 9; } else { nameLen = m_screenWidth - 1 - m_colWidthFiles - 2 - m_colWidthTotal - 2 - m_colWidthLeft - 2 - 9; } BString<1024> buffer; bool printFormatted = nameLen > 20; if (printFormatted) { BString<100> files("%i/%i", (int)nzbInfo->GetFileList()->size(), nzbInfo->GetPausedFileCount()); BString<1024> nameWithIds("%c%i%c%s%s %s", chBrace1, nzbInfo->GetId(), chBrace2, *priority, downloading, nzbInfo->GetName()); int64 unpausedRemainingSize = nzbInfo->GetRemainingSize() - nzbInfo->GetPausedSize(); CString remaining = Util::FormatSize(unpausedRemainingSize); CString total = Util::FormatSize(nzbInfo->GetSize()); BString<100> time; int currentDownloadSpeed = m_standBy ? 0 : m_currentDownloadSpeed; if (nzbInfo->GetPausedSize() > 0 && unpausedRemainingSize == 0) { time = "[paused]"; remaining = Util::FormatSize(nzbInfo->GetRemainingSize()); } else if (currentDownloadSpeed > 0 && !m_pauseDownload) { int64 remain_sec = (int64)(unpausedRemainingSize / currentDownloadSpeed); int h = (int)(remain_sec / 3600); int m = (int)((remain_sec % 3600) / 60); int s = (int)(remain_sec % 60); if (h < 100) { time.Format("%.2d:%.2d:%.2d", h, m, s); } else { time.Format("99:99:99"); } } if (calcColWidth) { int colWidthFiles = strlen(files); m_colWidthFiles = colWidthFiles > m_colWidthFiles ? colWidthFiles : m_colWidthFiles; int colWidthTotal = strlen(total); m_colWidthTotal = colWidthTotal > m_colWidthTotal ? colWidthTotal : m_colWidthTotal; int colWidthLeft = strlen(remaining); m_colWidthLeft = colWidthLeft > m_colWidthLeft ? colWidthLeft : m_colWidthLeft; } else { buffer.Format("%-*s %*s %*s %*s %8s", nameLen, *nameWithIds, m_colWidthFiles, *files, m_colWidthTotal, *total, m_colWidthLeft, *remaining, *time); } } else { buffer.Format("%c%i%c%s %s", chBrace1, nzbInfo->GetId(), chBrace2, downloading, nzbInfo->GetName()); } if (!calcColWidth) { PlotLine(buffer, row, 0, color); } }
void WinConsole::ResetFactoryDefaults() { BString<1024> path; CString errmsg; g_Options->SetPauseDownload(true); g_Options->SetPausePostProcess(true); char commonAppDataPath[MAX_PATH]; SHGetFolderPath(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, commonAppDataPath); // delete default directories const char* DefDirs[] = {"nzb", "tmp", "queue", "scripts"}; for (int i=0; i < 4; i++) { path.Format("%s\\NZBGet\\%s", commonAppDataPath, DefDirs[i]); // try to delete the directory int retry = 10; while (retry > 0 && FileSystem::DirectoryExists(path) && !FileSystem::DeleteDirectoryWithContent(path, errmsg)) { usleep(200 * 1000); retry--; } if (FileSystem::DirectoryExists(path)) { MessageBox(m_trayWindow, BString<1024>("Could not delete directory %s:\n%s.\nPlease delete the directory manually and try again.", *path, *errmsg), "NZBGet", MB_ICONERROR); return; } } // delete old config file in the program's directory path.Format("%s\\nzbget.conf", g_Options->GetAppDir()); FileSystem::DeleteFile(path); errmsg = FileSystem::GetLastErrorMessage(); if (FileSystem::FileExists(path)) { MessageBox(m_trayWindow, BString<1024>("Could not delete file %s:\n%s.\nPlease delete the file manually and try again.", *path, *errmsg), "NZBGet", MB_ICONERROR); return; } // delete config file in default directory path.Format("%s\\NZBGet\\nzbget.conf", commonAppDataPath); FileSystem::DeleteFile(path); errmsg = FileSystem::GetLastErrorMessage(); if (FileSystem::FileExists(path)) { MessageBox(m_trayWindow, BString<1024>("Could not delete file %s:\n%s.\nPlease delete the file manually and try again.", *path, *errmsg), "NZBGet", MB_ICONERROR); return; } // delete log files in default directory path.Format("%s\\NZBGet", commonAppDataPath); DirBrowser dir(path); while (const char* filename = dir.Next()) { if (Util::MatchFileExt(filename, ".log", ",")) { BString<1024> fullFilename("%s%c%s", *path, PATH_SEPARATOR, filename); FileSystem::DeleteFile(fullFilename); // ignore errors } } MessageBox(m_trayWindow, "The program has been reset to factory defaults.", "NZBGet", MB_ICONINFORMATION); mayStartBrowser = true; Reload(); }
void ArticleWriter::FlushCache() { detail("Flushing cache for %s", *m_infoName); bool directWrite = g_Options->GetDirectWrite() && m_fileInfo->GetOutputInitialized(); DiskFile outfile; bool needBufFile = false; int flushedArticles = 0; int64 flushedSize = 0; { ArticleCache::FlushGuard flushGuard = g_ArticleCache->GuardFlush(); std::vector<ArticleInfo*> cachedArticles; { Guard contentGuard = g_ArticleCache->GuardContent(); if (m_fileInfo->GetFlushLocked()) { return; } m_fileInfo->SetFlushLocked(true); cachedArticles.reserve(m_fileInfo->GetArticles()->size()); for (ArticleInfo* pa : m_fileInfo->GetArticles()) { if (pa->GetSegmentContent()) { cachedArticles.push_back(pa); } } } for (ArticleInfo* pa : cachedArticles) { if (m_fileInfo->GetDeleted() && !m_fileInfo->GetNzbInfo()->GetParking()) { // the file was deleted during flushing: stop flushing immediately break; } if (directWrite && !outfile.Active()) { if (!outfile.Open(m_fileInfo->GetOutputFilename(), DiskFile::omReadWrite)) { m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError, "Could not open file %s: %s", m_fileInfo->GetOutputFilename(), *FileSystem::GetLastErrorMessage()); // prevent multiple error messages pa->DiscardSegment(); flushedArticles++; break; } needBufFile = true; } BString<1024> destFile; if (!directWrite) { destFile.Format("%s.tmp", pa->GetResultFilename()); if (!outfile.Open(destFile, DiskFile::omWrite)) { m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError, "Could not create file %s: %s", *destFile, *FileSystem::GetLastErrorMessage()); // prevent multiple error messages pa->DiscardSegment(); flushedArticles++; break; } needBufFile = true; } if (outfile.Active() && needBufFile) { SetWriteBuffer(outfile, 0); needBufFile = false; } if (directWrite) { outfile.Seek(pa->GetSegmentOffset()); } if (!g_Options->GetSkipWrite()) { outfile.Write(pa->GetSegmentContent(), pa->GetSegmentSize()); } flushedSize += pa->GetSegmentSize(); flushedArticles++; pa->DiscardSegment(); if (!directWrite) { outfile.Close(); if (!FileSystem::MoveFile(destFile, pa->GetResultFilename())) { m_fileInfo->GetNzbInfo()->PrintMessage(Message::mkError, "Could not rename file %s to %s: %s", *destFile, pa->GetResultFilename(), *FileSystem::GetLastErrorMessage()); } } } outfile.Close(); { Guard contentGuard = g_ArticleCache->GuardContent(); m_fileInfo->SetCachedArticles(m_fileInfo->GetCachedArticles() - flushedArticles); m_fileInfo->SetFlushLocked(false); } } detail("Saved %i articles (%.2f MB) from cache into disk for %s", flushedArticles, (float)(flushedSize / 1024.0 / 1024.0), *m_infoName); }