예제 #1
0
파일: Updater.cpp 프로젝트: desg/OBS
BOOL FetchUpdaterModule()
{
    int responseCode;
    TCHAR updateFilePath[MAX_PATH];
    BYTE updateFileHash[20];
    TCHAR extraHeaders[256];

    tsprintf_s (updateFilePath, _countof(updateFilePath)-1, TEXT("%s\\updates\\updater.exe"), lpAppDataPath);

    if (CalculateFileHash(updateFilePath, updateFileHash))
    {
        TCHAR hashString[41];

        HashToString(updateFileHash, hashString);

        tsprintf_s (extraHeaders, _countof(extraHeaders)-1, TEXT("If-None-Match: %s"), hashString);
    }
    else
        extraHeaders[0] = 0;

    if (HTTPGetFile(TEXT("https://obsproject.com/update/updater.exe"), updateFilePath, extraHeaders, &responseCode))
    {
        if (responseCode != 200 && responseCode != 304)
            return FALSE;
    }

    return TRUE;
}
예제 #2
0
bool BuilderFileInfo::CheckOutOfDate(BuilderFileInfo& info, uint64_t configurationHash, bool bNoIntermediateFiles)
{
	if (!bNoIntermediateFiles && 
		(!GetCachedPathExists(info.ManifestPath) ||
		 !GetCachedPathExists(info.OutputPath)))
	{
		info.bOutOfDate = true;
		if (!GetCachedPathExists(info.ManifestPath))
		{
			Log(LogSeverity::Verbose, "[%s] Out of date because manifest path is non-existant.\n", info.SourcePath.GetFilename().c_str());
		}
		else if (!GetCachedPathExists(info.OutputPath))
		{
			Log(LogSeverity::Verbose, "[%s] Out of date because output path is non-existant.\n", info.SourcePath.GetFilename().c_str());
		}
	}
	else
	{
		uint64_t currentHash = info.Hash;

		if (!bNoIntermediateFiles && !info.LoadManifest())
		{
			info.bOutOfDate = true;
			Log(LogSeverity::Verbose, "[%s] Out of date because could not load manifest.\n", info.SourcePath.ToString().c_str());
		}
		else if (!info.SourcePath.IsEmpty() && info.Hash != currentHash)
		{
			Log(LogSeverity::Verbose, "[%s] Out of date because file hash was different.\n", info.SourcePath.ToString().c_str());
			info.bOutOfDate = true;
			info.Hash = currentHash;
		}
		else
		{
			for (const BuilderDependencyInfo& dependencyInfo : info.Dependencies)
			{
				uint64_t dependencyHash = CalculateFileHash(dependencyInfo.SourcePath, configurationHash);

				if (!GetCachedPathExists(dependencyInfo.SourcePath) ||
					 dependencyInfo.Hash != dependencyHash)
				{
					Log(LogSeverity::Verbose, "[%s] Out of date because dependency was out of date (hash=%i exists=%i): %s.\n",
						info.SourcePath.GetFilename().c_str(),
						dependencyInfo.Hash != dependencyHash,
						GetCachedPathExists(dependencyInfo.SourcePath),
						 dependencyInfo.SourcePath.ToString().c_str()
					);
				
					info.bOutOfDate = true;
					break;
				}
			}
		}
	}

	return info.bOutOfDate;
}
예제 #3
0
std::vector<BuilderFileInfo> BuilderFileInfo::GetMultipleFileInfos(
	const std::vector<Platform::Path>& paths,
	Platform::Path rootDirectory,
	Platform::Path outputDirectory,
	uint64_t configurationHash,
	bool bNoIntermediateFiles
)
{
	std::vector<BuilderFileInfo> result;

	for (const Platform::Path& path : paths)
	{
		BuilderFileInfo info;
		info.SourcePath = path;

		Platform::Path relativePath = rootDirectory.RelativeTo(path);
		assert(relativePath.IsRelative());

		info.OutputPath				= outputDirectory.AppendFragment(path.ChangeExtension("o").GetFilename(), true);
		info.ManifestPath			= info.OutputPath.ChangeExtension("build.manifest");
		info.bOutOfDate				= false;
		info.Hash					= CalculateFileHash(info.SourcePath, configurationHash);

		Platform::Path baseDirectory = info.OutputPath.GetDirectory();
		//if (!baseDirectory.Exists())
		if (!GetCachedPathExists(baseDirectory))
		{
			baseDirectory.CreateAsDirectory();
		}

		info.bOutOfDate = CheckOutOfDate(info, configurationHash, bNoIntermediateFiles);

		result.push_back(info);
	}

	return result;
}
예제 #4
0
파일: Updater.cpp 프로젝트: desg/OBS
DWORD WINAPI CheckUpdateThread (VOID *arg)
{
    int responseCode;
    TCHAR extraHeaders[256];
    BYTE manifestHash[20];
    TCHAR manifestPath[MAX_PATH];

    tsprintf_s (manifestPath, _countof(manifestPath)-1, TEXT("%s\\updates\\packages.xconfig"), lpAppDataPath);

    if (!CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        Log (TEXT("Updater: CryptAcquireContext failed: %08x"), GetLastError());
        return 1;
    }

    extraHeaders[0] = 0;

    if (CalculateFileHash(manifestPath, manifestHash))
    {
        TCHAR hashString[41];

        HashToString(manifestHash, hashString);

        tsprintf_s (extraHeaders, _countof(extraHeaders)-1, TEXT("If-None-Match: %s"), hashString);
    }
    
    //this is an arbitrary random number that we use to count the number of unique OBS installations
    //and is not associated with any kind of identifiable information
    String strGUID = GlobalConfig->GetString(TEXT("General"), TEXT("InstallGUID"));
    if (strGUID.IsEmpty())
    {
        GenerateGUID(strGUID);

        if (strGUID.IsValid())
            GlobalConfig->SetString(TEXT("General"), TEXT("InstallGUID"), strGUID);
    }

    if (strGUID.IsValid())
    {
        if (extraHeaders[0])
            scat(extraHeaders, TEXT("\n"));

        scat(extraHeaders, TEXT("X-OBS-GUID: "));
        scat(extraHeaders, strGUID);
    }

    if (HTTPGetFile(TEXT("https://obsproject.com/update/packages.xconfig"), manifestPath, extraHeaders, &responseCode))
    {
        if (responseCode == 200 || responseCode == 304)
        {
            String updateInfo;
            BOOL updatesAvailable;

            updateInfo = Str("Updater.NewUpdates");

            if (ParseUpdateManifest(manifestPath, &updatesAvailable, updateInfo))
            {
                if (updatesAvailable)
                {
                    updateInfo << TEXT("\r\n") << Str("Updater.DownloadNow");

                    if (MessageBox (NULL, updateInfo.Array(), Str("Updater.UpdatesAvailable"), MB_ICONQUESTION|MB_YESNO) == IDYES)
                    {
                        if (App->IsRunning())
                        {
                            if (MessageBox (NULL, Str("Updater.RunningWarning"), NULL, MB_ICONEXCLAMATION|MB_YESNO) == IDNO)
                                goto abortUpdate;
                        }

                        TCHAR updateFilePath[MAX_PATH];
                        TCHAR cwd[MAX_PATH];

                        GetModuleFileName(NULL, cwd, _countof(cwd)-1);
                        TCHAR *p = srchr(cwd, '\\');
                        if (p)
                            *p = 0;

                        tsprintf_s (updateFilePath, _countof(updateFilePath)-1, TEXT("%s\\updates\\updater.exe"), lpAppDataPath);

                        //note, can't use CreateProcess to launch as admin.
                        SHELLEXECUTEINFO execInfo;

                        zero(&execInfo, sizeof(execInfo));

                        execInfo.cbSize = sizeof(execInfo);
                        execInfo.lpFile = updateFilePath;
#ifndef _WIN64
                        execInfo.lpParameters = TEXT("Win32");
#else
                        execInfo.lpParameters = TEXT("Win64");
#endif
                        execInfo.lpDirectory = cwd;
                        execInfo.nShow = SW_SHOWNORMAL;

                        if (!ShellExecuteEx (&execInfo))
                        {
                            AppWarning(TEXT("Can't launch updater '%s': %d"), updateFilePath, GetLastError());
                            goto abortUpdate;
                        }

                        //force OBS to perform another update check immediately after updating in case of issues
                        //with the new version
                        GlobalConfig->SetInt(TEXT("General"), TEXT("LastUpdateCheck"), 0);

                        //since we're in a separate thread we can't just PostQuitMessage ourselves
                        SendMessage(hwndMain, WM_CLOSE, 0, 0);
                    }
                }
            }
        }
    }

abortUpdate:

    CryptReleaseContext(hProvider, 0);

    return 0;
}
예제 #5
0
파일: Updater.cpp 프로젝트: desg/OBS
BOOL ParseUpdateManifest (TCHAR *path, BOOL *updatesAvailable, String &description)
{
    XConfig manifest;
    XElement *root;

    if (!manifest.Open(path))
        return FALSE;

    root = manifest.GetRootElement();

    DWORD numPackages = root->NumElements();
    DWORD totalUpdatableFiles = 0;

    int priority, bestPriority = 999;

    for (DWORD i = 0; i < numPackages; i++)
    {
        XElement *package;
        package = root->GetElementByID(i);
        CTSTR packageName = package->GetName();

        //find out if this package is relevant to us
        String platform = package->GetString(TEXT("platform"));
        if (!platform)
            continue;

        if (scmp(platform, TEXT("all")))
        {
#ifndef _WIN64
            if (scmp(platform, TEXT("Win32")))
                continue;
#else
            if (scmp(platform, TEXT("Win64")))
                continue;
#endif
        }

        //what is it?
        String name = package->GetString(TEXT("name"));
        String version = package->GetString(TEXT("version"));

        //figure out where the files belong
        XDataItem *pathElement = package->GetDataItem(TEXT("path"));
        if (!pathElement)
            continue;

        CTSTR path = pathElement->GetData();

        if (path == NULL)
            path = TEXT("");

        if (!IsSafePath(path))
            continue;

        priority = package->GetInt(TEXT("priority"), 999);

        //get the file list for this package
        XElement *files = package->GetElement(TEXT("files"));
        if (!files)
            continue;

        DWORD numFiles = files->NumElements();
        DWORD numUpdatableFiles = 0;
        for (DWORD j = 0; j < numFiles; j++)
        {
            XElement *file = files->GetElementByID(j);

            String hash = file->GetString(TEXT("hash"));
            if (!hash || hash.Length() != 40)
                continue;

            String fileName = file->GetName();
            if (!fileName)
                continue;

            if (!IsSafeFilename(fileName))
                continue;

            String filePath;

            filePath << path;
            filePath << fileName;

            BYTE fileHash[20];
            TCHAR fileHashString[41];

            if (OSFileExists(filePath))
            {
                if (!CalculateFileHash(filePath, fileHash))
                    continue;
                
                HashToString(fileHash, fileHashString);
                if (!scmp(fileHashString, hash))
                    continue;
            }

            numUpdatableFiles++;
        }

        if (numUpdatableFiles)
        {
            if (version.Length())
                description << name << TEXT(" (") << version << TEXT(")\r\n");
            else
                description << name << TEXT("\r\n");

            if (priority < bestPriority)
                bestPriority = priority;
        }

        totalUpdatableFiles += numUpdatableFiles;
        numUpdatableFiles = 0;
    }

    manifest.Close();

    if (totalUpdatableFiles)
    {
        if (!FetchUpdaterModule())
            return FALSE;
    }

    if (bestPriority <= 5)
        *updatesAvailable = TRUE;
    else
        *updatesAvailable = FALSE;

    return TRUE;
}