1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: http.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $ 
   4 /* ###################################################################### 
   6    HTTPS Acquire Method - This is the HTTPS aquire method for APT. 
  10    ##################################################################### */ 
  12 // Include Files                                                        /*{{{*/ 
  13 #include <apt-pkg/fileutl.h> 
  14 #include <apt-pkg/acquire-method.h> 
  15 #include <apt-pkg/error.h> 
  16 #include <apt-pkg/hashes.h> 
  37 HttpsMethod::write_data(void *buffer
, size_t size
, size_t nmemb
, void *userp
) 
  39    HttpsMethod 
*me 
= (HttpsMethod 
*)userp
; 
  41    if(me
->File
->Write(buffer
, size
*nmemb
) != true) 
  48 HttpsMethod::progress_callback(void *clientp
, double dltotal
, double dlnow
,  
  49                               double ultotal
, double ulnow
) 
  51    HttpsMethod 
*me 
= (HttpsMethod 
*)clientp
; 
  52    if(dltotal 
> 0 && me
->Res
.Size 
== 0) { 
  53       me
->Res
.Size 
= (unsigned long)dltotal
; 
  54       me
->URIStart(me
->Res
); 
  59 void HttpsMethod::SetupProxy() 
  61    URI ServerName 
= Queue
->Uri
; 
  63    // Determine the proxy setting 
  64    if (getenv("http_proxy") == 0) 
  66       string DefProxy 
= _config
->Find("Acquire::http::Proxy"); 
  67       string SpecificProxy 
= _config
->Find("Acquire::http::Proxy::" + ServerName
.Host
); 
  68       if (SpecificProxy
.empty() == false) 
  70          if (SpecificProxy 
== "DIRECT") 
  73             Proxy 
= SpecificProxy
; 
  79    // Parse no_proxy, a , separated list of domains 
  80    if (getenv("no_proxy") != 0) 
  82       if (CheckDomainList(ServerName
.Host
,getenv("no_proxy")) == true) 
  86    // Determine what host and port to use based on the proxy settings 
  88    if (Proxy
.empty() == true || Proxy
.Host
.empty() == true) 
  94          curl_easy_setopt(curl
, CURLOPT_PROXYPORT
, Proxy
.Port
); 
  95       curl_easy_setopt(curl
, CURLOPT_PROXY
, Proxy
.Host
.c_str()); 
 100 // HttpsMethod::Fetch - Fetch an item                                   /*{{{*/ 
 101 // --------------------------------------------------------------------- 
 102 /* This adds an item to the pipeline. We keep the pipeline at a fixed 
 104 bool HttpsMethod::Fetch(FetchItem 
*Itm
) 
 108    struct curl_slist 
*headers
=NULL
;   
 109    char curl_errorstr
[CURL_ERROR_SIZE
]; 
 110    long curl_responsecode
; 
 113    //       - http::Pipeline-Depth 
 114    //       - error checking/reporting 
 115    //       - more debug options? (CURLOPT_DEBUGFUNCTION?) 
 117    curl_easy_reset(curl
); 
 121    curl_easy_setopt(curl
, CURLOPT_URL
, Itm
->Uri
.c_str()); 
 122    curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, write_data
); 
 123    curl_easy_setopt(curl
, CURLOPT_WRITEDATA
, this); 
 124    curl_easy_setopt(curl
, CURLOPT_PROGRESSFUNCTION
, progress_callback
); 
 125    curl_easy_setopt(curl
, CURLOPT_PROGRESSDATA
, this); 
 126    curl_easy_setopt(curl
, CURLOPT_NOPROGRESS
, false); 
 127    curl_easy_setopt(curl
, CURLOPT_FAILONERROR
, true); 
 128    curl_easy_setopt(curl
, CURLOPT_FILETIME
, true); 
 130    // FIXME: https: offer various options of verification 
 131    bool peer_verify 
= _config
->FindB("Acquire::https::Verify-Peer", false); 
 132    curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYPEER
, peer_verify
); 
 135    string pem 
= _config
->Find("Acquire::https::SslCert",""); 
 137       curl_easy_setopt(curl
, CURLOPT_SSLCERT
, pem
.c_str()); 
 140    string certdir 
= _config
->Find("Acquire::https::CaPath",""); 
 142       curl_easy_setopt(curl
, CURLOPT_CAPATH
, certdir
.c_str()); 
 145    int verify 
= _config
->FindI("Acquire::https::Verify-Host",2); 
 146    curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYHOST
, verify
); 
 149    if(_config
->FindB("Acquire::http::No-Cache",false) == false) 
 152       if (_config
->FindB("Acquire::http::No-Store",false) == true) 
 153          headers 
= curl_slist_append(headers
,"Cache-Control: no-store"); 
 154       ioprintf(ss
, "Cache-Control: max-age=%u", _config
->FindI("Acquire::http::Max-Age",0)); 
 155       headers 
= curl_slist_append(headers
, ss
.str().c_str()); 
 157       // cache disabled by user 
 158       headers 
= curl_slist_append(headers
, "Cache-Control: no-cache"); 
 159       headers 
= curl_slist_append(headers
, "Pragma: no-cache"); 
 161    curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, headers
); 
 164    int dlLimit 
= _config
->FindI("Acquire::http::Dl-Limit",0)*1024; 
 166       curl_easy_setopt(curl
, CURLOPT_MAX_RECV_SPEED_LARGE
, dlLimit
); 
 169    curl_easy_setopt(curl
, CURLOPT_USERAGENT
,"Debian APT-CURL/1.0 ("VERSION
")"); 
 172    int timeout 
= _config
->FindI("Acquire::http::Timeout",120); 
 173    curl_easy_setopt(curl
, CURLOPT_TIMEOUT
, timeout
); 
 174    curl_easy_setopt(curl
, CURLOPT_CONNECTTIMEOUT
, timeout
); 
 177    if(_config
->FindB("Debug::Acquire::https", false)) 
 178       curl_easy_setopt(curl
, CURLOPT_VERBOSE
, true); 
 181    curl_easy_setopt(curl
, CURLOPT_ERRORBUFFER
, curl_errorstr
); 
 183    // if we have the file send an if-range query with a range header 
 184    if (stat(Itm
->DestFile
.c_str(),&SBuf
) >= 0 && SBuf
.st_size 
> 0) 
 187       sprintf(Buf
,"Range: bytes=%li-\r\nIf-Range: %s\r\n", 
 188               (long)SBuf
.st_size 
- 1, 
 189               TimeRFC1123(SBuf
.st_mtime
).c_str()); 
 190       headers 
= curl_slist_append(headers
, Buf
); 
 192    else if(Itm
->LastModified 
> 0) 
 194       curl_easy_setopt(curl
, CURLOPT_TIMECONDITION
, CURL_TIMECOND_IFMODSINCE
); 
 195       curl_easy_setopt(curl
, CURLOPT_TIMEVALUE
, Itm
->LastModified
); 
 198    // go for it - if the file exists, append on it 
 199    File 
= new FileFd(Itm
->DestFile
, FileFd::WriteAny
); 
 200    if (File
->Size() > 0) 
 201       File
->Seek(File
->Size() - 1); 
 204    Res
.Filename 
= Itm
->DestFile
; 
 207    CURLcode success 
= curl_easy_perform(curl
); 
 208    curl_easy_getinfo(curl
, CURLINFO_RESPONSE_CODE
, &curl_responsecode
); 
 211    curl_easy_getinfo(curl
, CURLINFO_FILETIME
, &curl_servdate
); 
 216       unlink(File
->Name().c_str()); 
 217       _error
->Error(curl_errorstr
); 
 225    if (curl_servdate 
!= -1) { 
 226        UBuf
.actime 
= curl_servdate
; 
 227        UBuf
.modtime 
= curl_servdate
; 
 228        utime(File
->Name().c_str(),&UBuf
); 
 231    // check the downloaded result 
 233    if (stat(File
->Name().c_str(),&Buf
) == 0) 
 235       Res
.Filename 
= File
->Name(); 
 236       Res
.LastModified 
= Buf
.st_mtime
; 
 238       if (curl_responsecode 
== 304) 
 240          unlink(File
->Name().c_str()); 
 242          Res
.LastModified 
= Itm
->LastModified
; 
 247       Res
.Size 
= Buf
.st_size
; 
 252    FileFd 
Fd(Res
.Filename
, FileFd::ReadOnly
); 
 253    Hash
.AddFD(Fd
.Fd(), Fd
.Size()); 
 254    Res
.TakeHashes(Hash
); 
 262    curl_slist_free_all(headers
); 
 269    setlocale(LC_ALL
, ""); 
 272    curl_global_init(CURL_GLOBAL_SSL
) ;