BOOL TRecvDlg::OpenRecvFile(void) { char path[MAX_BUF]; if (MakePath(path, fileObj->isDir ? fileObj->path : fileObj->saveDir, fileObj->curFileInfo.Fname()) >= MAX_PATH_U8) return MessageBoxU8(path, GetLoadStrU8(IDS_PATHTOOLONG)), FALSE; if (IsSafePath(path, fileObj->curFileInfo.Fname()) == FALSE) return MessageBoxU8(path, GetLoadStrU8(IDS_NOTSAFEPATH)), FALSE; if ((fileObj->hFile = CreateFileU8(path, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) return fileObj->isDir ? FALSE : (MessageBoxU8(GetLoadStrU8(IDS_CREATEFAIL), path), FALSE); if (fileObj->curFileInfo.Attr() & IPMSG_FILE_RONLYOPT) SetFileAttributesU8(path, FILE_ATTRIBUTE_READONLY); //::SetFilePointer(fileObj->hFile, OFFSET, 0, FILE_BEGIN); //::SetEndOfFile(fileObj->hFile); return TRUE; }
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; }
BOOL TRecvDlg::RecvDirFile(void) { #define BIG_ALLOC 50 #define PEEK_SIZE 8 if (fileObj->status == FS_DIRFILESTART || fileObj->status == FS_TRANSINFO) { int size; if (fileObj->infoLen == 0) { if ((size = ::recv(fileObj->conInfo->sd, fileObj->info + (int)fileObj->offset, PEEK_SIZE - (int)fileObj->offset, 0)) <= 0) return FALSE; if ((fileObj->offset += size) < PEEK_SIZE) return TRUE; fileObj->info[fileObj->offset] = 0; if ((fileObj->infoLen = strtoul(fileObj->info, 0, 16)) >= sizeof(fileObj->info) -1 || fileObj->infoLen <= 0) return FALSE; // too big or small } if (fileObj->offset < fileObj->infoLen) { if ((size = ::recv(fileObj->conInfo->sd, fileObj->info + (int)fileObj->offset, fileObj->infoLen - (int)fileObj->offset, 0)) <= 0) return FALSE; fileObj->offset += size; } if (fileObj->offset == fileObj->infoLen) { fileObj->info[fileObj->infoLen] = 0; if (DecodeDirEntry(fileObj->info, &fileObj->curFileInfo, fileObj->u8fname) == FALSE) return FALSE; // Illegal entry fileObj->offset = fileObj->infoLen = 0; // 初期化 if (GET_MODE(fileObj->curFileInfo.Attr()) == IPMSG_FILE_DIR) { char buf[MAX_BUF]; const char *fname = fileObj->dirCnt == 0 ? fileObj->fileInfo->Fname() : fileObj->curFileInfo.Fname(); if (MakePath(buf, fileObj->path, fname) >= MAX_PATH_U8) return MessageBoxU8(buf, GetLoadStrU8(IDS_PATHTOOLONG)), FALSE; if (IsSafePath(buf, fname) == FALSE) return FALSE; if (CreateDirectoryU8(buf, NULL) == FALSE) return FALSE; strncpyz(fileObj->path, buf, MAX_PATH_U8); fileObj->dirCnt++; } else if (GET_MODE(fileObj->curFileInfo.Attr()) == IPMSG_FILE_RETPARENT) { if (fileObj->curFileInfo.Mtime()) // directory の time stamp をあわせる(NT系のみ) { FILETIME ft; HANDLE hFile; UnixTime2FileTime(fileObj->curFileInfo.Mtime(), &ft); if ((hFile = CreateFileU8(fileObj->path, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)) != INVALID_HANDLE_VALUE) { ::SetFileTime(hFile, NULL, NULL, &ft); ::CloseHandle(hFile); } } if (fileObj->curFileInfo.Attr() & IPMSG_FILE_RONLYOPT) SetFileAttributesU8(fileObj->path, FILE_ATTRIBUTE_READONLY); if (--fileObj->dirCnt <= 0) { fileObj->status = FS_COMPLETE; return TRUE; } if (PathToDir(fileObj->path, fileObj->path) == FALSE) return FALSE; } else { if (fileObj->dirCnt == 0) return FALSE; if (fileObj->curFileInfo.Size() == 0) // 0byte file { if (OpenRecvFile()) // 0byteの場合は作成失敗を無視 CloseRecvFile(TRUE); } fileObj->status = fileObj->curFileInfo.Size() ? FS_TRANSFILE : FS_TRANSINFO; } return TRUE; } } if (fileObj->status == FS_TRANSFILE) { if (RecvFile() != TRUE) { CloseRecvFile(); return FALSE; } if (fileObj->status == FS_ENDFILE) { CloseRecvFile(TRUE); fileObj->status = FS_TRANSINFO; } } return TRUE; }