Beispiel #1
0
// 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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}