// ZIPで圧縮されたRONのロード // 返り値:-2=一時ファイルを作成/-1=エラー/その他=ROMのサイズ // もし、ROMのサイズ>ROMバッファのサイズ の場合は一時ファイルを作成 s32 load_file_zip(char *filename) { struct SZIPFileHeader data; char tmp[MAX_PATH]; s32 retval = -1; u8 *buffer = NULL; u8 *cbuffer; char *ext; FILE_ID fd; FILE_ID tmp_fd; u32 zip_buffer_size; u32 write_tmp_flag = NO; u32 use_vram; use_vram = NO; zip_buffer_size = 16 * 1024 * 1024; cbuffer = malloc(zip_buffer_size); while(cbuffer == NULL) { zip_buffer_size -= (256 * 1024); if(zip_buffer_size == 0) break; cbuffer = malloc(zip_buffer_size); } if(zip_buffer_size == 0) { use_vram = YES; zip_buffer_size = ZIP_BUFFER_SIZE; cbuffer = (u8 *)UNIVERSAL_VRAM_ADDR; // 汎用フレームバッファを使用 } chdir(rom_path); FILE_OPEN(fd, filename, READ); if(!FILE_CHECK_VALID(fd)) return -1; { FILE_READ(fd, &data, sizeof(struct SZIPFileHeader)); // EDIT: Check if this is a zip file without worrying about endian // It checks for the following: 0x50 0x4B 0x03 0x04 (PK..) // Used to be: if(data.Sig != 0x04034b50) break; if( data.Sig[0] != 0x50 || data.Sig[1] != 0x4B || data.Sig[2] != 0x03 || data.Sig[3] != 0x04 ) { goto outcode; } FILE_READ(fd, tmp, data.FilenameLength); tmp[data.FilenameLength] = 0; // end string if(data.ExtraFieldLength) FILE_SEEK(fd, data.ExtraFieldLength, SEEK_CUR); if(data.GeneralBitFlag & 0x0008) { FILE_READ(fd, &data.DataDescriptor, sizeof(struct SZIPFileDataDescriptor)); } ext = strrchr(tmp, '.') + 1; // file is too big if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size) { write_tmp_flag = YES; // テンポラリを使用するフラグをONに FILE_OPEN(tmp_fd, ZIP_TMP, WRITE); } else write_tmp_flag = NO; if(!strncasecmp(ext, "bin", 3) || !strncasecmp(ext, "gba", 3)) { buffer = gamepak_rom; // ok, found switch(data.CompressionMethod) { case 0: //無圧縮 retval = data.DataDescriptor.UncompressedSize; FILE_READ(fd, buffer, retval); goto outcode; case 8: //圧縮 { z_stream stream = {0}; s32 err; /* * z.next_in = 入力ポインタ; * z.avail_in = 入力データの残量; * z.next_out = 出力ポインタ; * z.avail_out = 出力バッファの残量; */ stream.next_in = (Bytef*)cbuffer; stream.avail_in = (u32)zip_buffer_size; stream.next_out = (Bytef*)buffer; if(write_tmp_flag == NO) { stream.avail_out = data.DataDescriptor.UncompressedSize; retval = (u32)data.DataDescriptor.UncompressedSize; } else { stream.avail_out = gamepak_ram_buffer_size; retval = -2; } stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = inflateInit2(&stream, -MAX_WBITS); FILE_READ(fd, cbuffer, zip_buffer_size); sceKernelDcacheWritebackAll(); if(err == Z_OK) { while(err != Z_STREAM_END) { err = inflate(&stream, Z_SYNC_FLUSH); if(err == Z_BUF_ERROR) { stream.avail_in = (u32)zip_buffer_size; stream.next_in = (Bytef*)cbuffer; FILE_READ(fd, cbuffer, zip_buffer_size); sceKernelDcacheWritebackAll(); } if((write_tmp_flag == YES) && (stream.avail_out == 0)) /* 出力バッファが尽きれば */ { FILE_WRITE(tmp_fd, buffer, gamepak_ram_buffer_size); stream.next_out = buffer; /* 出力ポインタを元に戻す */ stream.avail_out = gamepak_ram_buffer_size; /* 出力バッファ残量を元に戻す */ } } if((write_tmp_flag == YES) && ((gamepak_ram_buffer_size - stream.avail_out) != 0)) FILE_WRITE(tmp_fd, buffer, gamepak_ram_buffer_size - stream.avail_out); err = Z_OK; inflateEnd(&stream); } goto outcode; } } } } outcode: FILE_CLOSE(fd); if(write_tmp_flag == YES) FILE_CLOSE(tmp_fd); if(use_vram == NO) free(cbuffer); chdir(main_path); return retval; }
int CloHttpCurl::TransferProcDOWNLOAD() { if( m_pAssoc->m_pTransferParam->bToBuffer ) // 下载到内存 { return TransferProcDOWNLOAD2(); } /////////////////////////////////////////////////////////////////// // 下载到文件 SetState( E_HTTPSTATE_RUNNING ); THttpMemoryBuffer headerBuffer; // 打开本地文件 THttpFileBuffer fileBuffer; memset(&fileBuffer, 0, sizeof(THttpFileBuffer)); // 关闭文件 #define FILE_CLOSE(p) if(p) { fclose(p);(p) = NULL;} // 看看文件夹是否有效 #ifdef _UNICODE if( !locom::CloFile::IsDirectoryExists( (CA2T)m_pAssoc->m_pTransferParam->cSavePath) ) { locom::CloFile::CreateDirectory( (CA2T)m_pAssoc->m_pTransferParam->cSavePath ); } #else if (!locom::CloFile::IsDirectoryExists(m_pAssoc->m_pTransferParam->cSavePath) ) { locom::CloFile::CreateDirectory(m_pAssoc->m_pTransferParam->cSavePath); } #endif // 启动curl //CURL_INIT(); m_pAssoc->m_curlHandle = curl_easy_init(); // 设置访问链接 CURLcode res = curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_URL, m_pAssoc->m_pTransferParam->cURL); _recvHeader: if( GetState() == E_HTTPSTATE_STOP ) //genobili add on 2010 - 01 - 22 { // 有错误发生 m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_FAILED; m_pAssoc->m_ErrorCode = E_HTTPTASK_ERR_CURL_EXCEPTION; FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); m_pAssoc->SetCURLCode(res); TaskCode(); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 任务结束 SetState( E_HTTPSTATE_STOP ); return -1; } // 设置附加的Header struct curl_slist *chunk = NULL; if( strlen(m_pAssoc->m_pTransferParam->cHead) > 0 ) { BuildCustomHeader(&chunk, m_pAssoc->m_pTransferParam->cHead); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HTTPHEADER, chunk); } // 设置代理信息 UpdateProxy(m_pAssoc->m_pTransferParam->cURL); // 设置访问Agent curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_USERAGENT, "httpclient-vika/1.0"); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_AUTOREFERER, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOBODY, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADER, 1); // 先设置获取Header的函数 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADERFUNCTION, ToHeaderCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADERDATA, (void *)&headerBuffer); curl_easy_perform(m_pAssoc->m_curlHandle); // 获取http code long httpCode = 0; res = curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_HTTP_CODE, &httpCode); // 成功 if( httpCode == 200 && CURLE_OK == res ) { double contentLength = 0; curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); char * url = NULL; curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_EFFECTIVE_URL, (void *)&url); // 如果没有指定文件名 if( !m_pAssoc->m_pTransferParam->bRename || strlen(m_pAssoc->m_pTransferParam->cNewName) == 0 ) { // 获取有效的文件名 std::string filename = GetUrlFileName(url); if( filename.length() > 0 ) { strcpy_s(m_pAssoc->m_pTransferParam->cNewName, 1024, filename.c_str()); } } if( strlen(m_pAssoc->m_pTransferParam->cNewName) > 0 ) { // 以新建方式,创建本地文件 std::string filePath = m_pAssoc->m_pTransferParam->cSavePath; filePath += "\\"; filePath += m_pAssoc->m_pTransferParam->cNewName; FILE * fp; errno_t err = fopen_s(&fp, filePath.c_str(), "w+b"); if( err != 0 ) { // 创建本地文件失败 m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_FAILED; m_pAssoc->m_ErrorCode = E_HTTPTASK_ERR_FAIL_TO_OPEN_LOCAL_FILE; // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER(headerBuffer.buffer); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 任务结束 SetState( E_HTTPSTATE_STOP ); return -1; } // 准备写文件了 fileBuffer.fp = fp; } else { // 错误,没有获取到文件名 m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_FAILED; m_pAssoc->m_ErrorCode = E_HTTPTASK_ERR_CANNOT_GET_REMOTE_FILE_NAME; // FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 任务结束 SetState( E_HTTPSTATE_STOP ); return -1; } // 先保存一下Header SAFE_NEW_MEMORYBUFFER(&m_pAssoc->m_HeaderRecv,headerBuffer.size,headerBuffer.size); COPY_MEMORYBUFFER(&headerBuffer,&m_pAssoc->m_HeaderRecv); goto _recvBody; } else if( httpCode == 302 && CURLE_OK == res ) { char * pUrl = NULL; curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_REDIRECT_URL, (void *)&pUrl); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_URL, pUrl); goto _recvHeader; } else { // 有错误发生 m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_FAILED; m_pAssoc->m_ErrorCode = E_HTTPTASK_ERR_CURL_EXCEPTION; FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); m_pAssoc->SetCURLCode(res); TaskCode(); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 任务结束 SetState( E_HTTPSTATE_STOP ); return -1; } _recvBody: curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOBODY, 0); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADER, 0); // 设置读取,保存数据的函数 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_WRITEFUNCTION, ToFileCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_WRITEDATA, (void *)&fileBuffer); // 设置progress回写 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_PROGRESSFUNCTION, ProgressCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_PROGRESSDATA, this); // 开始获取 res = curl_easy_perform(m_pAssoc->m_curlHandle); // 结果处理 int ret = 0; if( res == CURLE_OK ) { // 保存任务结果 m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_COMPLETE; ret = 0; } else { m_pAssoc->m_nResult = E_HTTPTRANS_RESULT_FAILED; m_pAssoc->m_ErrorCode = E_HTTPTASK_ERR_CURL_EXCEPTION; ret = -1; } FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); m_pAssoc->SetCURLCode( res ); TaskCode(); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 任务结束 SetState( E_HTTPSTATE_STOP ); return ret; }
int CloHttpCurl::TransferProcDOWNLOAD() { if( m_pAssoc->m_pTransferParam->bToBuffer ) // 下载到内存 { return TransferProcDOWNLOAD_TOBUFFER(); } /////////////////////////////////////////////////////////////////// // 下载到文件 SetState( E_HTTPSTATUS_START ); THttpMemoryBuffer headerBuffer; // 打开本地文件 THttpFileBuffer fileBuffer; memset(&fileBuffer, 0, sizeof(THttpFileBuffer)); // 关闭文件 #define FILE_CLOSE(p) if(p) { fclose(p);(p) = NULL;} // 看看文件夹是否有效 #ifdef _UNICODE if( !locom::CloFile::IsDirectoryExists( CA2T(m_pAssoc->m_pTransferParam->cSavePath) ) ) locom::CloFile::CreateDirectory( CA2T(m_pAssoc->m_pTransferParam->cSavePath) ); #else if (!locom::CloFile::IsDirectoryExists(m_pAssoc->m_pTransferParam->cSavePath) ) locom::CloFile::CreateDirectory(m_pAssoc->m_pTransferParam->cSavePath); #endif // 启动curl m_pAssoc->m_curlHandle = curl_easy_init(); // 设置访问链接 CURLcode code = curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_URL, m_pAssoc->m_pTransferParam->cURL); // 设置附加的Header struct curl_slist *chunk = NULL; _recvHeader: int state = GetState(); if( state != E_HTTPSTATUS_START ) // 防止 死loop , { // 有错误发生 FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); // 清理附加的Header参数信息 if( chunk != NULL ) { curl_slist_free_all(chunk); chunk = 0; } // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; m_pAssoc->SetErrCode(code); TaskCode(); // 任务结束 SetState( E_HTTPSTATUS_STOP ); return -1; } if( strlen(m_pAssoc->m_pTransferParam->cHead) > 0 ) { BuildCustomHeader(&chunk, m_pAssoc->m_pTransferParam->cHead); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HTTPHEADER, chunk); } // 设置代理信息 UpdateProxy(m_pAssoc->m_pTransferParam->cURL); // 设置访问Agent curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_USERAGENT, GetUserAgent() ); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_AUTOREFERER, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOBODY, 1); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADER, 1); // 先设置获取Header的函数 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADERFUNCTION, ToHeaderCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADERDATA, (void *)&headerBuffer); curl_easy_perform(m_pAssoc->m_curlHandle); // 获取http code m_pAssoc->m_lhttpCode = 0; code = curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_HTTP_CODE, &m_pAssoc->m_lhttpCode); // 成功 if( m_pAssoc->m_lhttpCode == 200 && CURLE_OK == code ) { double contentLength = 0; char * url = NULL; curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_EFFECTIVE_URL, (void *)&url); // 如果没有指定文件名 if( !m_pAssoc->m_pTransferParam->bRename || strlen(m_pAssoc->m_pTransferParam->cNewFileName) == 0 ) { // 获取有效的文件名 std::string filename = GetUrlFileName(url); if( filename.length() > 0 ) { strcpy_s(m_pAssoc->m_pTransferParam->cNewFileName, 1024, filename.c_str()); } } if( strlen(m_pAssoc->m_pTransferParam->cNewFileName) > 0 ) { // 以新建方式,创建本地文件 char cNewFile[ConstLocalFileLength]; strcpy(cNewFile , m_pAssoc->m_pTransferParam->cSavePath ); strcat( cNewFile , "\\"); strcat( cNewFile , m_pAssoc->m_pTransferParam->cNewFileName ); FILE * fp = fopen(cNewFile , "w+b"); if( fp == 0 ) { // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER(headerBuffer.buffer); // 清理附加的Header参数信息 if( chunk != NULL ) { curl_slist_free_all(chunk); chunk = 0; } // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; // 创建本地文件失败 m_pAssoc->SetErrCode( HTTPE_CREATE_FILE ); TaskCode(); // 任务结束 SetState( E_HTTPSTATUS_STOP ); return -1; } // 准备写文件了 fileBuffer.fp = fp; } else { // FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); // 清理附加的Header参数信息 if( chunk != NULL ) { curl_slist_free_all(chunk); chunk = 0; } // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; m_pAssoc->SetErrCode( HTTPE_FILE_NAME_NULL ); TaskCode(); // 任务结束 SetState( E_HTTPSTATUS_STOP ); return -1; } // 先保存一下Header SAFE_NEW_MEMORYBUFFER(&m_pAssoc->m_HeaderRecv,headerBuffer.size,headerBuffer.size); COPY_MEMORYBUFFER(&headerBuffer,&m_pAssoc->m_HeaderRecv); goto _recvBody; } else if( m_pAssoc->m_lhttpCode == 302 && CURLE_OK == code ) { // 重定向 char * pUrl = NULL; curl_easy_getinfo(m_pAssoc->m_curlHandle, CURLINFO_REDIRECT_URL, (void *)&pUrl); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_URL, pUrl); // 清理附加的Header参数信息 if( chunk != NULL ) { curl_slist_free_all(chunk); chunk = 0; } goto _recvHeader; } else { // 有错误发生 FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); // 清理附加的Header参数信息 if( chunk != NULL ) curl_slist_free_all(chunk); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; m_pAssoc->SetErrCode(code); TaskCode(); // 任务结束 SetState( E_HTTPSTATUS_STOP ); return -1; } _recvBody: curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOBODY, 0); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_HEADER, 0); // 设置读取,保存数据的函数 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_WRITEFUNCTION, ToFileCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_WRITEDATA, (void *)&fileBuffer); // 设置progress回写 curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_PROGRESSFUNCTION, ProgressCallback); curl_easy_setopt(m_pAssoc->m_curlHandle, CURLOPT_PROGRESSDATA, this); // 开始获取 code = curl_easy_perform(m_pAssoc->m_curlHandle); FILE_CLOSE( fileBuffer.fp ); // 清理缓存 // 这里有点特别,因为是通过 BufferRealloc() 分配的 SAFE_FREE_BUFFER( headerBuffer.buffer ); // 清理附加的Header参数信息 if( chunk != NULL ) curl_slist_free_all(chunk); // 释放curl curl_easy_cleanup(m_pAssoc->m_curlHandle); m_pAssoc->m_curlHandle = NULL; m_pAssoc->SetErrCode( code ); TaskCode(); // 任务结束 SetState( E_HTTPSTATUS_STOP ); return (code != CURLE_OK)?-1:0; }