Example #1
0
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;
	}
}
Example #2
0
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;
}
Example #3
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
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);
}
Example #8
0
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);
}
Example #9
0
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;
}
Example #10
0
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);
	}
}
Example #11
0
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();
}
Example #12
0
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);
}