http.con commit http: add Accept-Language header if possible (f18604b)
   1#include "git-compat-util.h"
   2#include "http.h"
   3#include "pack.h"
   4#include "sideband.h"
   5#include "run-command.h"
   6#include "url.h"
   7#include "urlmatch.h"
   8#include "credential.h"
   9#include "version.h"
  10#include "pkt-line.h"
  11
  12int active_requests;
  13int http_is_verbose;
  14size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
  15
  16#if LIBCURL_VERSION_NUM >= 0x070a06
  17#define LIBCURL_CAN_HANDLE_AUTH_ANY
  18#endif
  19
  20static int min_curl_sessions = 1;
  21static int curl_session_count;
  22#ifdef USE_CURL_MULTI
  23static int max_requests = -1;
  24static CURLM *curlm;
  25#endif
  26#ifndef NO_CURL_EASY_DUPHANDLE
  27static CURL *curl_default;
  28#endif
  29
  30#define PREV_BUF_SIZE 4096
  31#define RANGE_HEADER_SIZE 30
  32
  33char curl_errorstr[CURL_ERROR_SIZE];
  34
  35static int curl_ssl_verify = -1;
  36static int curl_ssl_try;
  37static const char *ssl_cert;
  38#if LIBCURL_VERSION_NUM >= 0x070903
  39static const char *ssl_key;
  40#endif
  41#if LIBCURL_VERSION_NUM >= 0x070908
  42static const char *ssl_capath;
  43#endif
  44static const char *ssl_cainfo;
  45static long curl_low_speed_limit = -1;
  46static long curl_low_speed_time = -1;
  47static int curl_ftp_no_epsv;
  48static const char *curl_http_proxy;
  49static const char *curl_cookie_file;
  50static int curl_save_cookies;
  51struct credential http_auth = CREDENTIAL_INIT;
  52static int http_proactive_auth;
  53static const char *user_agent;
  54
  55#if LIBCURL_VERSION_NUM >= 0x071700
  56/* Use CURLOPT_KEYPASSWD as is */
  57#elif LIBCURL_VERSION_NUM >= 0x070903
  58#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
  59#else
  60#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD
  61#endif
  62
  63static struct credential cert_auth = CREDENTIAL_INIT;
  64static int ssl_cert_password_required;
  65
  66static struct curl_slist *pragma_header;
  67static struct curl_slist *no_pragma_header;
  68
  69static struct active_request_slot *active_queue_head;
  70
  71static char *cached_accept_language;
  72
  73size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
  74{
  75        size_t size = eltsize * nmemb;
  76        struct buffer *buffer = buffer_;
  77
  78        if (size > buffer->buf.len - buffer->posn)
  79                size = buffer->buf.len - buffer->posn;
  80        memcpy(ptr, buffer->buf.buf + buffer->posn, size);
  81        buffer->posn += size;
  82
  83        return size;
  84}
  85
  86#ifndef NO_CURL_IOCTL
  87curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
  88{
  89        struct buffer *buffer = clientp;
  90
  91        switch (cmd) {
  92        case CURLIOCMD_NOP:
  93                return CURLIOE_OK;
  94
  95        case CURLIOCMD_RESTARTREAD:
  96                buffer->posn = 0;
  97                return CURLIOE_OK;
  98
  99        default:
 100                return CURLIOE_UNKNOWNCMD;
 101        }
 102}
 103#endif
 104
 105size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 106{
 107        size_t size = eltsize * nmemb;
 108        struct strbuf *buffer = buffer_;
 109
 110        strbuf_add(buffer, ptr, size);
 111        return size;
 112}
 113
 114size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
 115{
 116        return eltsize * nmemb;
 117}
 118
 119#ifdef USE_CURL_MULTI
 120static void process_curl_messages(void)
 121{
 122        int num_messages;
 123        struct active_request_slot *slot;
 124        CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
 125
 126        while (curl_message != NULL) {
 127                if (curl_message->msg == CURLMSG_DONE) {
 128                        int curl_result = curl_message->data.result;
 129                        slot = active_queue_head;
 130                        while (slot != NULL &&
 131                               slot->curl != curl_message->easy_handle)
 132                                slot = slot->next;
 133                        if (slot != NULL) {
 134                                curl_multi_remove_handle(curlm, slot->curl);
 135                                slot->curl_result = curl_result;
 136                                finish_active_slot(slot);
 137                        } else {
 138                                fprintf(stderr, "Received DONE message for unknown request!\n");
 139                        }
 140                } else {
 141                        fprintf(stderr, "Unknown CURL message received: %d\n",
 142                                (int)curl_message->msg);
 143                }
 144                curl_message = curl_multi_info_read(curlm, &num_messages);
 145        }
 146}
 147#endif
 148
 149static int http_options(const char *var, const char *value, void *cb)
 150{
 151        if (!strcmp("http.sslverify", var)) {
 152                curl_ssl_verify = git_config_bool(var, value);
 153                return 0;
 154        }
 155        if (!strcmp("http.sslcert", var))
 156                return git_config_string(&ssl_cert, var, value);
 157#if LIBCURL_VERSION_NUM >= 0x070903
 158        if (!strcmp("http.sslkey", var))
 159                return git_config_string(&ssl_key, var, value);
 160#endif
 161#if LIBCURL_VERSION_NUM >= 0x070908
 162        if (!strcmp("http.sslcapath", var))
 163                return git_config_string(&ssl_capath, var, value);
 164#endif
 165        if (!strcmp("http.sslcainfo", var))
 166                return git_config_string(&ssl_cainfo, var, value);
 167        if (!strcmp("http.sslcertpasswordprotected", var)) {
 168                ssl_cert_password_required = git_config_bool(var, value);
 169                return 0;
 170        }
 171        if (!strcmp("http.ssltry", var)) {
 172                curl_ssl_try = git_config_bool(var, value);
 173                return 0;
 174        }
 175        if (!strcmp("http.minsessions", var)) {
 176                min_curl_sessions = git_config_int(var, value);
 177#ifndef USE_CURL_MULTI
 178                if (min_curl_sessions > 1)
 179                        min_curl_sessions = 1;
 180#endif
 181                return 0;
 182        }
 183#ifdef USE_CURL_MULTI
 184        if (!strcmp("http.maxrequests", var)) {
 185                max_requests = git_config_int(var, value);
 186                return 0;
 187        }
 188#endif
 189        if (!strcmp("http.lowspeedlimit", var)) {
 190                curl_low_speed_limit = (long)git_config_int(var, value);
 191                return 0;
 192        }
 193        if (!strcmp("http.lowspeedtime", var)) {
 194                curl_low_speed_time = (long)git_config_int(var, value);
 195                return 0;
 196        }
 197
 198        if (!strcmp("http.noepsv", var)) {
 199                curl_ftp_no_epsv = git_config_bool(var, value);
 200                return 0;
 201        }
 202        if (!strcmp("http.proxy", var))
 203                return git_config_string(&curl_http_proxy, var, value);
 204
 205        if (!strcmp("http.cookiefile", var))
 206                return git_config_string(&curl_cookie_file, var, value);
 207        if (!strcmp("http.savecookies", var)) {
 208                curl_save_cookies = git_config_bool(var, value);
 209                return 0;
 210        }
 211
 212        if (!strcmp("http.postbuffer", var)) {
 213                http_post_buffer = git_config_int(var, value);
 214                if (http_post_buffer < LARGE_PACKET_MAX)
 215                        http_post_buffer = LARGE_PACKET_MAX;
 216                return 0;
 217        }
 218
 219        if (!strcmp("http.useragent", var))
 220                return git_config_string(&user_agent, var, value);
 221
 222        /* Fall back on the default ones */
 223        return git_default_config(var, value, cb);
 224}
 225
 226static void init_curl_http_auth(CURL *result)
 227{
 228        if (!http_auth.username)
 229                return;
 230
 231        credential_fill(&http_auth);
 232
 233#if LIBCURL_VERSION_NUM >= 0x071301
 234        curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
 235        curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
 236#else
 237        {
 238                static struct strbuf up = STRBUF_INIT;
 239                /*
 240                 * Note that we assume we only ever have a single set of
 241                 * credentials in a given program run, so we do not have
 242                 * to worry about updating this buffer, only setting its
 243                 * initial value.
 244                 */
 245                if (!up.len)
 246                        strbuf_addf(&up, "%s:%s",
 247                                http_auth.username, http_auth.password);
 248                curl_easy_setopt(result, CURLOPT_USERPWD, up.buf);
 249        }
 250#endif
 251}
 252
 253static int has_cert_password(void)
 254{
 255        if (ssl_cert == NULL || ssl_cert_password_required != 1)
 256                return 0;
 257        if (!cert_auth.password) {
 258                cert_auth.protocol = xstrdup("cert");
 259                cert_auth.username = xstrdup("");
 260                cert_auth.path = xstrdup(ssl_cert);
 261                credential_fill(&cert_auth);
 262        }
 263        return 1;
 264}
 265
 266#if LIBCURL_VERSION_NUM >= 0x071900
 267static void set_curl_keepalive(CURL *c)
 268{
 269        curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1);
 270}
 271
 272#elif LIBCURL_VERSION_NUM >= 0x071000
 273static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type)
 274{
 275        int ka = 1;
 276        int rc;
 277        socklen_t len = (socklen_t)sizeof(ka);
 278
 279        if (type != CURLSOCKTYPE_IPCXN)
 280                return 0;
 281
 282        rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len);
 283        if (rc < 0)
 284                warning("unable to set SO_KEEPALIVE on socket %s",
 285                        strerror(errno));
 286
 287        return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */
 288}
 289
 290static void set_curl_keepalive(CURL *c)
 291{
 292        curl_easy_setopt(c, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
 293}
 294
 295#else
 296static void set_curl_keepalive(CURL *c)
 297{
 298        /* not supported on older curl versions */
 299}
 300#endif
 301
 302static CURL *get_curl_handle(void)
 303{
 304        CURL *result = curl_easy_init();
 305
 306        if (!result)
 307                die("curl_easy_init failed");
 308
 309        if (!curl_ssl_verify) {
 310                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
 311                curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0);
 312        } else {
 313                /* Verify authenticity of the peer's certificate */
 314                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1);
 315                /* The name in the cert must match whom we tried to connect */
 316                curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2);
 317        }
 318
 319#if LIBCURL_VERSION_NUM >= 0x070907
 320        curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 321#endif
 322#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
 323        curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 324#endif
 325
 326        if (http_proactive_auth)
 327                init_curl_http_auth(result);
 328
 329        if (ssl_cert != NULL)
 330                curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
 331        if (has_cert_password())
 332                curl_easy_setopt(result, CURLOPT_KEYPASSWD, cert_auth.password);
 333#if LIBCURL_VERSION_NUM >= 0x070903
 334        if (ssl_key != NULL)
 335                curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
 336#endif
 337#if LIBCURL_VERSION_NUM >= 0x070908
 338        if (ssl_capath != NULL)
 339                curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
 340#endif
 341        if (ssl_cainfo != NULL)
 342                curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
 343
 344        if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
 345                curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
 346                                 curl_low_speed_limit);
 347                curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
 348                                 curl_low_speed_time);
 349        }
 350
 351        curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
 352#if LIBCURL_VERSION_NUM >= 0x071301
 353        curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
 354#elif LIBCURL_VERSION_NUM >= 0x071101
 355        curl_easy_setopt(result, CURLOPT_POST301, 1);
 356#endif
 357
 358        if (getenv("GIT_CURL_VERBOSE"))
 359                curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
 360
 361        curl_easy_setopt(result, CURLOPT_USERAGENT,
 362                user_agent ? user_agent : git_user_agent());
 363
 364        if (curl_ftp_no_epsv)
 365                curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
 366
 367#ifdef CURLOPT_USE_SSL
 368        if (curl_ssl_try)
 369                curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 370#endif
 371
 372        if (curl_http_proxy) {
 373                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
 374                curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 375        }
 376
 377        set_curl_keepalive(result);
 378
 379        return result;
 380}
 381
 382static void set_from_env(const char **var, const char *envname)
 383{
 384        const char *val = getenv(envname);
 385        if (val)
 386                *var = val;
 387}
 388
 389void http_init(struct remote *remote, const char *url, int proactive_auth)
 390{
 391        char *low_speed_limit;
 392        char *low_speed_time;
 393        char *normalized_url;
 394        struct urlmatch_config config = { STRING_LIST_INIT_DUP };
 395
 396        config.section = "http";
 397        config.key = NULL;
 398        config.collect_fn = http_options;
 399        config.cascade_fn = git_default_config;
 400        config.cb = NULL;
 401
 402        http_is_verbose = 0;
 403        normalized_url = url_normalize(url, &config.url);
 404
 405        git_config(urlmatch_config_entry, &config);
 406        free(normalized_url);
 407
 408        if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
 409                die("curl_global_init failed");
 410
 411        http_proactive_auth = proactive_auth;
 412
 413        if (remote && remote->http_proxy)
 414                curl_http_proxy = xstrdup(remote->http_proxy);
 415
 416        pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
 417        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 418
 419#ifdef USE_CURL_MULTI
 420        {
 421                char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
 422                if (http_max_requests != NULL)
 423                        max_requests = atoi(http_max_requests);
 424        }
 425
 426        curlm = curl_multi_init();
 427        if (!curlm)
 428                die("curl_multi_init failed");
 429#endif
 430
 431        if (getenv("GIT_SSL_NO_VERIFY"))
 432                curl_ssl_verify = 0;
 433
 434        set_from_env(&ssl_cert, "GIT_SSL_CERT");
 435#if LIBCURL_VERSION_NUM >= 0x070903
 436        set_from_env(&ssl_key, "GIT_SSL_KEY");
 437#endif
 438#if LIBCURL_VERSION_NUM >= 0x070908
 439        set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
 440#endif
 441        set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
 442
 443        set_from_env(&user_agent, "GIT_HTTP_USER_AGENT");
 444
 445        low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
 446        if (low_speed_limit != NULL)
 447                curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
 448        low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
 449        if (low_speed_time != NULL)
 450                curl_low_speed_time = strtol(low_speed_time, NULL, 10);
 451
 452        if (curl_ssl_verify == -1)
 453                curl_ssl_verify = 1;
 454
 455        curl_session_count = 0;
 456#ifdef USE_CURL_MULTI
 457        if (max_requests < 1)
 458                max_requests = DEFAULT_MAX_REQUESTS;
 459#endif
 460
 461        if (getenv("GIT_CURL_FTP_NO_EPSV"))
 462                curl_ftp_no_epsv = 1;
 463
 464        if (url) {
 465                credential_from_url(&http_auth, url);
 466                if (!ssl_cert_password_required &&
 467                    getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
 468                    starts_with(url, "https://"))
 469                        ssl_cert_password_required = 1;
 470        }
 471
 472#ifndef NO_CURL_EASY_DUPHANDLE
 473        curl_default = get_curl_handle();
 474#endif
 475}
 476
 477void http_cleanup(void)
 478{
 479        struct active_request_slot *slot = active_queue_head;
 480
 481        while (slot != NULL) {
 482                struct active_request_slot *next = slot->next;
 483                if (slot->curl != NULL) {
 484#ifdef USE_CURL_MULTI
 485                        curl_multi_remove_handle(curlm, slot->curl);
 486#endif
 487                        curl_easy_cleanup(slot->curl);
 488                }
 489                free(slot);
 490                slot = next;
 491        }
 492        active_queue_head = NULL;
 493
 494#ifndef NO_CURL_EASY_DUPHANDLE
 495        curl_easy_cleanup(curl_default);
 496#endif
 497
 498#ifdef USE_CURL_MULTI
 499        curl_multi_cleanup(curlm);
 500#endif
 501        curl_global_cleanup();
 502
 503        curl_slist_free_all(pragma_header);
 504        pragma_header = NULL;
 505
 506        curl_slist_free_all(no_pragma_header);
 507        no_pragma_header = NULL;
 508
 509        if (curl_http_proxy) {
 510                free((void *)curl_http_proxy);
 511                curl_http_proxy = NULL;
 512        }
 513
 514        if (cert_auth.password != NULL) {
 515                memset(cert_auth.password, 0, strlen(cert_auth.password));
 516                free(cert_auth.password);
 517                cert_auth.password = NULL;
 518        }
 519        ssl_cert_password_required = 0;
 520
 521        free(cached_accept_language);
 522        cached_accept_language = NULL;
 523}
 524
 525struct active_request_slot *get_active_slot(void)
 526{
 527        struct active_request_slot *slot = active_queue_head;
 528        struct active_request_slot *newslot;
 529
 530#ifdef USE_CURL_MULTI
 531        int num_transfers;
 532
 533        /* Wait for a slot to open up if the queue is full */
 534        while (active_requests >= max_requests) {
 535                curl_multi_perform(curlm, &num_transfers);
 536                if (num_transfers < active_requests)
 537                        process_curl_messages();
 538        }
 539#endif
 540
 541        while (slot != NULL && slot->in_use)
 542                slot = slot->next;
 543
 544        if (slot == NULL) {
 545                newslot = xmalloc(sizeof(*newslot));
 546                newslot->curl = NULL;
 547                newslot->in_use = 0;
 548                newslot->next = NULL;
 549
 550                slot = active_queue_head;
 551                if (slot == NULL) {
 552                        active_queue_head = newslot;
 553                } else {
 554                        while (slot->next != NULL)
 555                                slot = slot->next;
 556                        slot->next = newslot;
 557                }
 558                slot = newslot;
 559        }
 560
 561        if (slot->curl == NULL) {
 562#ifdef NO_CURL_EASY_DUPHANDLE
 563                slot->curl = get_curl_handle();
 564#else
 565                slot->curl = curl_easy_duphandle(curl_default);
 566#endif
 567                curl_session_count++;
 568        }
 569
 570        active_requests++;
 571        slot->in_use = 1;
 572        slot->results = NULL;
 573        slot->finished = NULL;
 574        slot->callback_data = NULL;
 575        slot->callback_func = NULL;
 576        curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file);
 577        if (curl_save_cookies)
 578                curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
 579        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
 580        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
 581        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
 582        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
 583        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
 584        curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL);
 585        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
 586        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
 587        curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
 588        if (http_auth.password)
 589                init_curl_http_auth(slot->curl);
 590
 591        return slot;
 592}
 593
 594int start_active_slot(struct active_request_slot *slot)
 595{
 596#ifdef USE_CURL_MULTI
 597        CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
 598        int num_transfers;
 599
 600        if (curlm_result != CURLM_OK &&
 601            curlm_result != CURLM_CALL_MULTI_PERFORM) {
 602                active_requests--;
 603                slot->in_use = 0;
 604                return 0;
 605        }
 606
 607        /*
 608         * We know there must be something to do, since we just added
 609         * something.
 610         */
 611        curl_multi_perform(curlm, &num_transfers);
 612#endif
 613        return 1;
 614}
 615
 616#ifdef USE_CURL_MULTI
 617struct fill_chain {
 618        void *data;
 619        int (*fill)(void *);
 620        struct fill_chain *next;
 621};
 622
 623static struct fill_chain *fill_cfg;
 624
 625void add_fill_function(void *data, int (*fill)(void *))
 626{
 627        struct fill_chain *new = xmalloc(sizeof(*new));
 628        struct fill_chain **linkp = &fill_cfg;
 629        new->data = data;
 630        new->fill = fill;
 631        new->next = NULL;
 632        while (*linkp)
 633                linkp = &(*linkp)->next;
 634        *linkp = new;
 635}
 636
 637void fill_active_slots(void)
 638{
 639        struct active_request_slot *slot = active_queue_head;
 640
 641        while (active_requests < max_requests) {
 642                struct fill_chain *fill;
 643                for (fill = fill_cfg; fill; fill = fill->next)
 644                        if (fill->fill(fill->data))
 645                                break;
 646
 647                if (!fill)
 648                        break;
 649        }
 650
 651        while (slot != NULL) {
 652                if (!slot->in_use && slot->curl != NULL
 653                        && curl_session_count > min_curl_sessions) {
 654                        curl_easy_cleanup(slot->curl);
 655                        slot->curl = NULL;
 656                        curl_session_count--;
 657                }
 658                slot = slot->next;
 659        }
 660}
 661
 662void step_active_slots(void)
 663{
 664        int num_transfers;
 665        CURLMcode curlm_result;
 666
 667        do {
 668                curlm_result = curl_multi_perform(curlm, &num_transfers);
 669        } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
 670        if (num_transfers < active_requests) {
 671                process_curl_messages();
 672                fill_active_slots();
 673        }
 674}
 675#endif
 676
 677void run_active_slot(struct active_request_slot *slot)
 678{
 679#ifdef USE_CURL_MULTI
 680        fd_set readfds;
 681        fd_set writefds;
 682        fd_set excfds;
 683        int max_fd;
 684        struct timeval select_timeout;
 685        int finished = 0;
 686
 687        slot->finished = &finished;
 688        while (!finished) {
 689                step_active_slots();
 690
 691                if (slot->in_use) {
 692#if LIBCURL_VERSION_NUM >= 0x070f04
 693                        long curl_timeout;
 694                        curl_multi_timeout(curlm, &curl_timeout);
 695                        if (curl_timeout == 0) {
 696                                continue;
 697                        } else if (curl_timeout == -1) {
 698                                select_timeout.tv_sec  = 0;
 699                                select_timeout.tv_usec = 50000;
 700                        } else {
 701                                select_timeout.tv_sec  =  curl_timeout / 1000;
 702                                select_timeout.tv_usec = (curl_timeout % 1000) * 1000;
 703                        }
 704#else
 705                        select_timeout.tv_sec  = 0;
 706                        select_timeout.tv_usec = 50000;
 707#endif
 708
 709                        max_fd = -1;
 710                        FD_ZERO(&readfds);
 711                        FD_ZERO(&writefds);
 712                        FD_ZERO(&excfds);
 713                        curl_multi_fdset(curlm, &readfds, &writefds, &excfds, &max_fd);
 714
 715                        /*
 716                         * It can happen that curl_multi_timeout returns a pathologically
 717                         * long timeout when curl_multi_fdset returns no file descriptors
 718                         * to read.  See commit message for more details.
 719                         */
 720                        if (max_fd < 0 &&
 721                            (select_timeout.tv_sec > 0 ||
 722                             select_timeout.tv_usec > 50000)) {
 723                                select_timeout.tv_sec  = 0;
 724                                select_timeout.tv_usec = 50000;
 725                        }
 726
 727                        select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout);
 728                }
 729        }
 730#else
 731        while (slot->in_use) {
 732                slot->curl_result = curl_easy_perform(slot->curl);
 733                finish_active_slot(slot);
 734        }
 735#endif
 736}
 737
 738static void closedown_active_slot(struct active_request_slot *slot)
 739{
 740        active_requests--;
 741        slot->in_use = 0;
 742}
 743
 744static void release_active_slot(struct active_request_slot *slot)
 745{
 746        closedown_active_slot(slot);
 747        if (slot->curl && curl_session_count > min_curl_sessions) {
 748#ifdef USE_CURL_MULTI
 749                curl_multi_remove_handle(curlm, slot->curl);
 750#endif
 751                curl_easy_cleanup(slot->curl);
 752                slot->curl = NULL;
 753                curl_session_count--;
 754        }
 755#ifdef USE_CURL_MULTI
 756        fill_active_slots();
 757#endif
 758}
 759
 760void finish_active_slot(struct active_request_slot *slot)
 761{
 762        closedown_active_slot(slot);
 763        curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code);
 764
 765        if (slot->finished != NULL)
 766                (*slot->finished) = 1;
 767
 768        /* Store slot results so they can be read after the slot is reused */
 769        if (slot->results != NULL) {
 770                slot->results->curl_result = slot->curl_result;
 771                slot->results->http_code = slot->http_code;
 772#if LIBCURL_VERSION_NUM >= 0x070a08
 773                curl_easy_getinfo(slot->curl, CURLINFO_HTTPAUTH_AVAIL,
 774                                  &slot->results->auth_avail);
 775#else
 776                slot->results->auth_avail = 0;
 777#endif
 778        }
 779
 780        /* Run callback if appropriate */
 781        if (slot->callback_func != NULL)
 782                slot->callback_func(slot->callback_data);
 783}
 784
 785void finish_all_active_slots(void)
 786{
 787        struct active_request_slot *slot = active_queue_head;
 788
 789        while (slot != NULL)
 790                if (slot->in_use) {
 791                        run_active_slot(slot);
 792                        slot = active_queue_head;
 793                } else {
 794                        slot = slot->next;
 795                }
 796}
 797
 798/* Helpers for modifying and creating URLs */
 799static inline int needs_quote(int ch)
 800{
 801        if (((ch >= 'A') && (ch <= 'Z'))
 802                        || ((ch >= 'a') && (ch <= 'z'))
 803                        || ((ch >= '0') && (ch <= '9'))
 804                        || (ch == '/')
 805                        || (ch == '-')
 806                        || (ch == '.'))
 807                return 0;
 808        return 1;
 809}
 810
 811static char *quote_ref_url(const char *base, const char *ref)
 812{
 813        struct strbuf buf = STRBUF_INIT;
 814        const char *cp;
 815        int ch;
 816
 817        end_url_with_slash(&buf, base);
 818
 819        for (cp = ref; (ch = *cp) != 0; cp++)
 820                if (needs_quote(ch))
 821                        strbuf_addf(&buf, "%%%02x", ch);
 822                else
 823                        strbuf_addch(&buf, *cp);
 824
 825        return strbuf_detach(&buf, NULL);
 826}
 827
 828void append_remote_object_url(struct strbuf *buf, const char *url,
 829                              const char *hex,
 830                              int only_two_digit_prefix)
 831{
 832        end_url_with_slash(buf, url);
 833
 834        strbuf_addf(buf, "objects/%.*s/", 2, hex);
 835        if (!only_two_digit_prefix)
 836                strbuf_addf(buf, "%s", hex+2);
 837}
 838
 839char *get_remote_object_url(const char *url, const char *hex,
 840                            int only_two_digit_prefix)
 841{
 842        struct strbuf buf = STRBUF_INIT;
 843        append_remote_object_url(&buf, url, hex, only_two_digit_prefix);
 844        return strbuf_detach(&buf, NULL);
 845}
 846
 847int handle_curl_result(struct slot_results *results)
 848{
 849        /*
 850         * If we see a failing http code with CURLE_OK, we have turned off
 851         * FAILONERROR (to keep the server's custom error response), and should
 852         * translate the code into failure here.
 853         */
 854        if (results->curl_result == CURLE_OK &&
 855            results->http_code >= 400) {
 856                results->curl_result = CURLE_HTTP_RETURNED_ERROR;
 857                /*
 858                 * Normally curl will already have put the "reason phrase"
 859                 * from the server into curl_errorstr; unfortunately without
 860                 * FAILONERROR it is lost, so we can give only the numeric
 861                 * status code.
 862                 */
 863                snprintf(curl_errorstr, sizeof(curl_errorstr),
 864                         "The requested URL returned error: %ld",
 865                         results->http_code);
 866        }
 867
 868        if (results->curl_result == CURLE_OK) {
 869                credential_approve(&http_auth);
 870                return HTTP_OK;
 871        } else if (missing_target(results))
 872                return HTTP_MISSING_TARGET;
 873        else if (results->http_code == 401) {
 874                if (http_auth.username && http_auth.password) {
 875                        credential_reject(&http_auth);
 876                        return HTTP_NOAUTH;
 877                } else {
 878                        return HTTP_REAUTH;
 879                }
 880        } else {
 881#if LIBCURL_VERSION_NUM >= 0x070c00
 882                if (!curl_errorstr[0])
 883                        strlcpy(curl_errorstr,
 884                                curl_easy_strerror(results->curl_result),
 885                                sizeof(curl_errorstr));
 886#endif
 887                return HTTP_ERROR;
 888        }
 889}
 890
 891int run_one_slot(struct active_request_slot *slot,
 892                 struct slot_results *results)
 893{
 894        slot->results = results;
 895        if (!start_active_slot(slot)) {
 896                snprintf(curl_errorstr, sizeof(curl_errorstr),
 897                         "failed to start HTTP request");
 898                return HTTP_START_FAILED;
 899        }
 900
 901        run_active_slot(slot);
 902        return handle_curl_result(results);
 903}
 904
 905static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
 906{
 907        char *ptr;
 908        CURLcode ret;
 909
 910        strbuf_reset(buf);
 911        ret = curl_easy_getinfo(curl, info, &ptr);
 912        if (!ret && ptr)
 913                strbuf_addstr(buf, ptr);
 914        return ret;
 915}
 916
 917/*
 918 * Check for and extract a content-type parameter. "raw"
 919 * should be positioned at the start of the potential
 920 * parameter, with any whitespace already removed.
 921 *
 922 * "name" is the name of the parameter. The value is appended
 923 * to "out".
 924 */
 925static int extract_param(const char *raw, const char *name,
 926                         struct strbuf *out)
 927{
 928        size_t len = strlen(name);
 929
 930        if (strncasecmp(raw, name, len))
 931                return -1;
 932        raw += len;
 933
 934        if (*raw != '=')
 935                return -1;
 936        raw++;
 937
 938        while (*raw && !isspace(*raw) && *raw != ';')
 939                strbuf_addch(out, *raw++);
 940        return 0;
 941}
 942
 943/*
 944 * Extract a normalized version of the content type, with any
 945 * spaces suppressed, all letters lowercased, and no trailing ";"
 946 * or parameters.
 947 *
 948 * Note that we will silently remove even invalid whitespace. For
 949 * example, "text / plain" is specifically forbidden by RFC 2616,
 950 * but "text/plain" is the only reasonable output, and this keeps
 951 * our code simple.
 952 *
 953 * If the "charset" argument is not NULL, store the value of any
 954 * charset parameter there.
 955 *
 956 * Example:
 957 *   "TEXT/PLAIN; charset=utf-8" -> "text/plain", "utf-8"
 958 *   "text / plain" -> "text/plain"
 959 */
 960static void extract_content_type(struct strbuf *raw, struct strbuf *type,
 961                                 struct strbuf *charset)
 962{
 963        const char *p;
 964
 965        strbuf_reset(type);
 966        strbuf_grow(type, raw->len);
 967        for (p = raw->buf; *p; p++) {
 968                if (isspace(*p))
 969                        continue;
 970                if (*p == ';') {
 971                        p++;
 972                        break;
 973                }
 974                strbuf_addch(type, tolower(*p));
 975        }
 976
 977        if (!charset)
 978                return;
 979
 980        strbuf_reset(charset);
 981        while (*p) {
 982                while (isspace(*p) || *p == ';')
 983                        p++;
 984                if (!extract_param(p, "charset", charset))
 985                        return;
 986                while (*p && !isspace(*p))
 987                        p++;
 988        }
 989
 990        if (!charset->len && starts_with(type->buf, "text/"))
 991                strbuf_addstr(charset, "ISO-8859-1");
 992}
 993
 994/*
 995 * Guess the user's preferred languages from the value in LANGUAGE environment
 996 * variable and LC_MESSAGES locale category if NO_GETTEXT is not defined.
 997 *
 998 * The result can be a colon-separated list like "ko:ja:en".
 999 */
1000static const char *get_preferred_languages(void)
1001{
1002        const char *retval;
1003
1004        retval = getenv("LANGUAGE");
1005        if (retval && *retval)
1006                return retval;
1007
1008#ifndef NO_GETTEXT
1009        retval = setlocale(LC_MESSAGES, NULL);
1010        if (retval && *retval &&
1011                strcmp(retval, "C") &&
1012                strcmp(retval, "POSIX"))
1013                return retval;
1014#endif
1015
1016        return NULL;
1017}
1018
1019static void write_accept_language(struct strbuf *buf)
1020{
1021        /*
1022         * MAX_DECIMAL_PLACES must not be larger than 3. If it is larger than
1023         * that, q-value will be smaller than 0.001, the minimum q-value the
1024         * HTTP specification allows. See
1025         * http://tools.ietf.org/html/rfc7231#section-5.3.1 for q-value.
1026         */
1027        const int MAX_DECIMAL_PLACES = 3;
1028        const int MAX_LANGUAGE_TAGS = 1000;
1029        const int MAX_ACCEPT_LANGUAGE_HEADER_SIZE = 4000;
1030        char **language_tags = NULL;
1031        int num_langs = 0;
1032        const char *s = get_preferred_languages();
1033        int i;
1034        struct strbuf tag = STRBUF_INIT;
1035
1036        /* Don't add Accept-Language header if no language is preferred. */
1037        if (!s)
1038                return;
1039
1040        /*
1041         * Split the colon-separated string of preferred languages into
1042         * language_tags array.
1043         */
1044        do {
1045                /* collect language tag */
1046                for (; *s && (isalnum(*s) || *s == '_'); s++)
1047                        strbuf_addch(&tag, *s == '_' ? '-' : *s);
1048
1049                /* skip .codeset, @modifier and any other unnecessary parts */
1050                while (*s && *s != ':')
1051                        s++;
1052
1053                if (tag.len) {
1054                        num_langs++;
1055                        REALLOC_ARRAY(language_tags, num_langs);
1056                        language_tags[num_langs - 1] = strbuf_detach(&tag, NULL);
1057                        if (num_langs >= MAX_LANGUAGE_TAGS - 1) /* -1 for '*' */
1058                                break;
1059                }
1060        } while (*s++);
1061
1062        /* write Accept-Language header into buf */
1063        if (num_langs) {
1064                int last_buf_len = 0;
1065                int max_q;
1066                int decimal_places;
1067                char q_format[32];
1068
1069                /* add '*' */
1070                REALLOC_ARRAY(language_tags, num_langs + 1);
1071                language_tags[num_langs++] = "*"; /* it's OK; this won't be freed */
1072
1073                /* compute decimal_places */
1074                for (max_q = 1, decimal_places = 0;
1075                     max_q < num_langs && decimal_places <= MAX_DECIMAL_PLACES;
1076                     decimal_places++, max_q *= 10)
1077                        ;
1078
1079                sprintf(q_format, ";q=0.%%0%dd", decimal_places);
1080
1081                strbuf_addstr(buf, "Accept-Language: ");
1082
1083                for (i = 0; i < num_langs; i++) {
1084                        if (i > 0)
1085                                strbuf_addstr(buf, ", ");
1086
1087                        strbuf_addstr(buf, language_tags[i]);
1088
1089                        if (i > 0)
1090                                strbuf_addf(buf, q_format, max_q - i);
1091
1092                        if (buf->len > MAX_ACCEPT_LANGUAGE_HEADER_SIZE) {
1093                                strbuf_remove(buf, last_buf_len, buf->len - last_buf_len);
1094                                break;
1095                        }
1096
1097                        last_buf_len = buf->len;
1098                }
1099        }
1100
1101        /* free language tags -- last one is a static '*' */
1102        for (i = 0; i < num_langs - 1; i++)
1103                free(language_tags[i]);
1104        free(language_tags);
1105}
1106
1107/*
1108 * Get an Accept-Language header which indicates user's preferred languages.
1109 *
1110 * Examples:
1111 *   LANGUAGE= -> ""
1112 *   LANGUAGE=ko:en -> "Accept-Language: ko, en; q=0.9, *; q=0.1"
1113 *   LANGUAGE=ko_KR.UTF-8:sr@latin -> "Accept-Language: ko-KR, sr; q=0.9, *; q=0.1"
1114 *   LANGUAGE=ko LANG=en_US.UTF-8 -> "Accept-Language: ko, *; q=0.1"
1115 *   LANGUAGE= LANG=en_US.UTF-8 -> "Accept-Language: en-US, *; q=0.1"
1116 *   LANGUAGE= LANG=C -> ""
1117 */
1118static const char *get_accept_language(void)
1119{
1120        if (!cached_accept_language) {
1121                struct strbuf buf = STRBUF_INIT;
1122                write_accept_language(&buf);
1123                if (buf.len > 0)
1124                        cached_accept_language = strbuf_detach(&buf, NULL);
1125        }
1126
1127        return cached_accept_language;
1128}
1129
1130/* http_request() targets */
1131#define HTTP_REQUEST_STRBUF     0
1132#define HTTP_REQUEST_FILE       1
1133
1134static int http_request(const char *url,
1135                        void *result, int target,
1136                        const struct http_get_options *options)
1137{
1138        struct active_request_slot *slot;
1139        struct slot_results results;
1140        struct curl_slist *headers = NULL;
1141        struct strbuf buf = STRBUF_INIT;
1142        const char *accept_language;
1143        int ret;
1144
1145        slot = get_active_slot();
1146        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
1147
1148        if (result == NULL) {
1149                curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
1150        } else {
1151                curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
1152                curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
1153
1154                if (target == HTTP_REQUEST_FILE) {
1155                        long posn = ftell(result);
1156                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
1157                                         fwrite);
1158                        if (posn > 0) {
1159                                strbuf_addf(&buf, "Range: bytes=%ld-", posn);
1160                                headers = curl_slist_append(headers, buf.buf);
1161                                strbuf_reset(&buf);
1162                        }
1163                } else
1164                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
1165                                         fwrite_buffer);
1166        }
1167
1168        accept_language = get_accept_language();
1169
1170        if (accept_language)
1171                headers = curl_slist_append(headers, accept_language);
1172
1173        strbuf_addstr(&buf, "Pragma:");
1174        if (options && options->no_cache)
1175                strbuf_addstr(&buf, " no-cache");
1176        if (options && options->keep_error)
1177                curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
1178
1179        headers = curl_slist_append(headers, buf.buf);
1180
1181        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1182        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
1183        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
1184
1185        ret = run_one_slot(slot, &results);
1186
1187        if (options && options->content_type) {
1188                struct strbuf raw = STRBUF_INIT;
1189                curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, &raw);
1190                extract_content_type(&raw, options->content_type,
1191                                     options->charset);
1192                strbuf_release(&raw);
1193        }
1194
1195        if (options && options->effective_url)
1196                curlinfo_strbuf(slot->curl, CURLINFO_EFFECTIVE_URL,
1197                                options->effective_url);
1198
1199        curl_slist_free_all(headers);
1200        strbuf_release(&buf);
1201
1202        return ret;
1203}
1204
1205/*
1206 * Update the "base" url to a more appropriate value, as deduced by
1207 * redirects seen when requesting a URL starting with "url".
1208 *
1209 * The "asked" parameter is a URL that we asked curl to access, and must begin
1210 * with "base".
1211 *
1212 * The "got" parameter is the URL that curl reported to us as where we ended
1213 * up.
1214 *
1215 * Returns 1 if we updated the base url, 0 otherwise.
1216 *
1217 * Our basic strategy is to compare "base" and "asked" to find the bits
1218 * specific to our request. We then strip those bits off of "got" to yield the
1219 * new base. So for example, if our base is "http://example.com/foo.git",
1220 * and we ask for "http://example.com/foo.git/info/refs", we might end up
1221 * with "https://other.example.com/foo.git/info/refs". We would want the
1222 * new URL to become "https://other.example.com/foo.git".
1223 *
1224 * Note that this assumes a sane redirect scheme. It's entirely possible
1225 * in the example above to end up at a URL that does not even end in
1226 * "info/refs".  In such a case we simply punt, as there is not much we can
1227 * do (and such a scheme is unlikely to represent a real git repository,
1228 * which means we are likely about to abort anyway).
1229 */
1230static int update_url_from_redirect(struct strbuf *base,
1231                                    const char *asked,
1232                                    const struct strbuf *got)
1233{
1234        const char *tail;
1235        size_t tail_len;
1236
1237        if (!strcmp(asked, got->buf))
1238                return 0;
1239
1240        if (!skip_prefix(asked, base->buf, &tail))
1241                die("BUG: update_url_from_redirect: %s is not a superset of %s",
1242                    asked, base->buf);
1243
1244        tail_len = strlen(tail);
1245
1246        if (got->len < tail_len ||
1247            strcmp(tail, got->buf + got->len - tail_len))
1248                return 0; /* insane redirect scheme */
1249
1250        strbuf_reset(base);
1251        strbuf_add(base, got->buf, got->len - tail_len);
1252        return 1;
1253}
1254
1255static int http_request_reauth(const char *url,
1256                               void *result, int target,
1257                               struct http_get_options *options)
1258{
1259        int ret = http_request(url, result, target, options);
1260
1261        if (options && options->effective_url && options->base_url) {
1262                if (update_url_from_redirect(options->base_url,
1263                                             url, options->effective_url)) {
1264                        credential_from_url(&http_auth, options->base_url->buf);
1265                        url = options->effective_url->buf;
1266                }
1267        }
1268
1269        if (ret != HTTP_REAUTH)
1270                return ret;
1271
1272        /*
1273         * If we are using KEEP_ERROR, the previous request may have
1274         * put cruft into our output stream; we should clear it out before
1275         * making our next request. We only know how to do this for
1276         * the strbuf case, but that is enough to satisfy current callers.
1277         */
1278        if (options && options->keep_error) {
1279                switch (target) {
1280                case HTTP_REQUEST_STRBUF:
1281                        strbuf_reset(result);
1282                        break;
1283                default:
1284                        die("BUG: HTTP_KEEP_ERROR is only supported with strbufs");
1285                }
1286        }
1287
1288        credential_fill(&http_auth);
1289
1290        return http_request(url, result, target, options);
1291}
1292
1293int http_get_strbuf(const char *url,
1294                    struct strbuf *result,
1295                    struct http_get_options *options)
1296{
1297        return http_request_reauth(url, result, HTTP_REQUEST_STRBUF, options);
1298}
1299
1300/*
1301 * Downloads a URL and stores the result in the given file.
1302 *
1303 * If a previous interrupted download is detected (i.e. a previous temporary
1304 * file is still around) the download is resumed.
1305 */
1306static int http_get_file(const char *url, const char *filename,
1307                         struct http_get_options *options)
1308{
1309        int ret;
1310        struct strbuf tmpfile = STRBUF_INIT;
1311        FILE *result;
1312
1313        strbuf_addf(&tmpfile, "%s.temp", filename);
1314        result = fopen(tmpfile.buf, "a");
1315        if (!result) {
1316                error("Unable to open local file %s", tmpfile.buf);
1317                ret = HTTP_ERROR;
1318                goto cleanup;
1319        }
1320
1321        ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options);
1322        fclose(result);
1323
1324        if (ret == HTTP_OK && move_temp_to_file(tmpfile.buf, filename))
1325                ret = HTTP_ERROR;
1326cleanup:
1327        strbuf_release(&tmpfile);
1328        return ret;
1329}
1330
1331int http_fetch_ref(const char *base, struct ref *ref)
1332{
1333        struct http_get_options options = {0};
1334        char *url;
1335        struct strbuf buffer = STRBUF_INIT;
1336        int ret = -1;
1337
1338        options.no_cache = 1;
1339
1340        url = quote_ref_url(base, ref->name);
1341        if (http_get_strbuf(url, &buffer, &options) == HTTP_OK) {
1342                strbuf_rtrim(&buffer);
1343                if (buffer.len == 40)
1344                        ret = get_sha1_hex(buffer.buf, ref->old_sha1);
1345                else if (starts_with(buffer.buf, "ref: ")) {
1346                        ref->symref = xstrdup(buffer.buf + 5);
1347                        ret = 0;
1348                }
1349        }
1350
1351        strbuf_release(&buffer);
1352        free(url);
1353        return ret;
1354}
1355
1356/* Helpers for fetching packs */
1357static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
1358{
1359        char *url, *tmp;
1360        struct strbuf buf = STRBUF_INIT;
1361
1362        if (http_is_verbose)
1363                fprintf(stderr, "Getting index for pack %s\n", sha1_to_hex(sha1));
1364
1365        end_url_with_slash(&buf, base_url);
1366        strbuf_addf(&buf, "objects/pack/pack-%s.idx", sha1_to_hex(sha1));
1367        url = strbuf_detach(&buf, NULL);
1368
1369        strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(sha1));
1370        tmp = strbuf_detach(&buf, NULL);
1371
1372        if (http_get_file(url, tmp, NULL) != HTTP_OK) {
1373                error("Unable to get pack index %s", url);
1374                free(tmp);
1375                tmp = NULL;
1376        }
1377
1378        free(url);
1379        return tmp;
1380}
1381
1382static int fetch_and_setup_pack_index(struct packed_git **packs_head,
1383        unsigned char *sha1, const char *base_url)
1384{
1385        struct packed_git *new_pack;
1386        char *tmp_idx = NULL;
1387        int ret;
1388
1389        if (has_pack_index(sha1)) {
1390                new_pack = parse_pack_index(sha1, NULL);
1391                if (!new_pack)
1392                        return -1; /* parse_pack_index() already issued error message */
1393                goto add_pack;
1394        }
1395
1396        tmp_idx = fetch_pack_index(sha1, base_url);
1397        if (!tmp_idx)
1398                return -1;
1399
1400        new_pack = parse_pack_index(sha1, tmp_idx);
1401        if (!new_pack) {
1402                unlink(tmp_idx);
1403                free(tmp_idx);
1404
1405                return -1; /* parse_pack_index() already issued error message */
1406        }
1407
1408        ret = verify_pack_index(new_pack);
1409        if (!ret) {
1410                close_pack_index(new_pack);
1411                ret = move_temp_to_file(tmp_idx, sha1_pack_index_name(sha1));
1412        }
1413        free(tmp_idx);
1414        if (ret)
1415                return -1;
1416
1417add_pack:
1418        new_pack->next = *packs_head;
1419        *packs_head = new_pack;
1420        return 0;
1421}
1422
1423int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
1424{
1425        struct http_get_options options = {0};
1426        int ret = 0, i = 0;
1427        char *url, *data;
1428        struct strbuf buf = STRBUF_INIT;
1429        unsigned char sha1[20];
1430
1431        end_url_with_slash(&buf, base_url);
1432        strbuf_addstr(&buf, "objects/info/packs");
1433        url = strbuf_detach(&buf, NULL);
1434
1435        options.no_cache = 1;
1436        ret = http_get_strbuf(url, &buf, &options);
1437        if (ret != HTTP_OK)
1438                goto cleanup;
1439
1440        data = buf.buf;
1441        while (i < buf.len) {
1442                switch (data[i]) {
1443                case 'P':
1444                        i++;
1445                        if (i + 52 <= buf.len &&
1446                            starts_with(data + i, " pack-") &&
1447                            starts_with(data + i + 46, ".pack\n")) {
1448                                get_sha1_hex(data + i + 6, sha1);
1449                                fetch_and_setup_pack_index(packs_head, sha1,
1450                                                      base_url);
1451                                i += 51;
1452                                break;
1453                        }
1454                default:
1455                        while (i < buf.len && data[i] != '\n')
1456                                i++;
1457                }
1458                i++;
1459        }
1460
1461cleanup:
1462        free(url);
1463        return ret;
1464}
1465
1466void release_http_pack_request(struct http_pack_request *preq)
1467{
1468        if (preq->packfile != NULL) {
1469                fclose(preq->packfile);
1470                preq->packfile = NULL;
1471        }
1472        if (preq->range_header != NULL) {
1473                curl_slist_free_all(preq->range_header);
1474                preq->range_header = NULL;
1475        }
1476        preq->slot = NULL;
1477        free(preq->url);
1478}
1479
1480int finish_http_pack_request(struct http_pack_request *preq)
1481{
1482        struct packed_git **lst;
1483        struct packed_git *p = preq->target;
1484        char *tmp_idx;
1485        struct child_process ip = CHILD_PROCESS_INIT;
1486        const char *ip_argv[8];
1487
1488        close_pack_index(p);
1489
1490        fclose(preq->packfile);
1491        preq->packfile = NULL;
1492
1493        lst = preq->lst;
1494        while (*lst != p)
1495                lst = &((*lst)->next);
1496        *lst = (*lst)->next;
1497
1498        tmp_idx = xstrdup(preq->tmpfile);
1499        strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"),
1500               ".idx.temp");
1501
1502        ip_argv[0] = "index-pack";
1503        ip_argv[1] = "-o";
1504        ip_argv[2] = tmp_idx;
1505        ip_argv[3] = preq->tmpfile;
1506        ip_argv[4] = NULL;
1507
1508        ip.argv = ip_argv;
1509        ip.git_cmd = 1;
1510        ip.no_stdin = 1;
1511        ip.no_stdout = 1;
1512
1513        if (run_command(&ip)) {
1514                unlink(preq->tmpfile);
1515                unlink(tmp_idx);
1516                free(tmp_idx);
1517                return -1;
1518        }
1519
1520        unlink(sha1_pack_index_name(p->sha1));
1521
1522        if (move_temp_to_file(preq->tmpfile, sha1_pack_name(p->sha1))
1523         || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
1524                free(tmp_idx);
1525                return -1;
1526        }
1527
1528        install_packed_git(p);
1529        free(tmp_idx);
1530        return 0;
1531}
1532
1533struct http_pack_request *new_http_pack_request(
1534        struct packed_git *target, const char *base_url)
1535{
1536        long prev_posn = 0;
1537        char range[RANGE_HEADER_SIZE];
1538        struct strbuf buf = STRBUF_INIT;
1539        struct http_pack_request *preq;
1540
1541        preq = xcalloc(1, sizeof(*preq));
1542        preq->target = target;
1543
1544        end_url_with_slash(&buf, base_url);
1545        strbuf_addf(&buf, "objects/pack/pack-%s.pack",
1546                sha1_to_hex(target->sha1));
1547        preq->url = strbuf_detach(&buf, NULL);
1548
1549        snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp",
1550                sha1_pack_name(target->sha1));
1551        preq->packfile = fopen(preq->tmpfile, "a");
1552        if (!preq->packfile) {
1553                error("Unable to open local file %s for pack",
1554                      preq->tmpfile);
1555                goto abort;
1556        }
1557
1558        preq->slot = get_active_slot();
1559        curl_easy_setopt(preq->slot->curl, CURLOPT_FILE, preq->packfile);
1560        curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
1561        curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url);
1562        curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
1563                no_pragma_header);
1564
1565        /*
1566         * If there is data present from a previous transfer attempt,
1567         * resume where it left off
1568         */
1569        prev_posn = ftell(preq->packfile);
1570        if (prev_posn>0) {
1571                if (http_is_verbose)
1572                        fprintf(stderr,
1573                                "Resuming fetch of pack %s at byte %ld\n",
1574                                sha1_to_hex(target->sha1), prev_posn);
1575                sprintf(range, "Range: bytes=%ld-", prev_posn);
1576                preq->range_header = curl_slist_append(NULL, range);
1577                curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
1578                        preq->range_header);
1579        }
1580
1581        return preq;
1582
1583abort:
1584        free(preq->url);
1585        free(preq);
1586        return NULL;
1587}
1588
1589/* Helpers for fetching objects (loose) */
1590static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
1591                               void *data)
1592{
1593        unsigned char expn[4096];
1594        size_t size = eltsize * nmemb;
1595        int posn = 0;
1596        struct http_object_request *freq =
1597                (struct http_object_request *)data;
1598        do {
1599                ssize_t retval = xwrite(freq->localfile,
1600                                        (char *) ptr + posn, size - posn);
1601                if (retval < 0)
1602                        return posn;
1603                posn += retval;
1604        } while (posn < size);
1605
1606        freq->stream.avail_in = size;
1607        freq->stream.next_in = (void *)ptr;
1608        do {
1609                freq->stream.next_out = expn;
1610                freq->stream.avail_out = sizeof(expn);
1611                freq->zret = git_inflate(&freq->stream, Z_SYNC_FLUSH);
1612                git_SHA1_Update(&freq->c, expn,
1613                                sizeof(expn) - freq->stream.avail_out);
1614        } while (freq->stream.avail_in && freq->zret == Z_OK);
1615        return size;
1616}
1617
1618struct http_object_request *new_http_object_request(const char *base_url,
1619        unsigned char *sha1)
1620{
1621        char *hex = sha1_to_hex(sha1);
1622        const char *filename;
1623        char prevfile[PATH_MAX];
1624        int prevlocal;
1625        char prev_buf[PREV_BUF_SIZE];
1626        ssize_t prev_read = 0;
1627        long prev_posn = 0;
1628        char range[RANGE_HEADER_SIZE];
1629        struct curl_slist *range_header = NULL;
1630        struct http_object_request *freq;
1631
1632        freq = xcalloc(1, sizeof(*freq));
1633        hashcpy(freq->sha1, sha1);
1634        freq->localfile = -1;
1635
1636        filename = sha1_file_name(sha1);
1637        snprintf(freq->tmpfile, sizeof(freq->tmpfile),
1638                 "%s.temp", filename);
1639
1640        snprintf(prevfile, sizeof(prevfile), "%s.prev", filename);
1641        unlink_or_warn(prevfile);
1642        rename(freq->tmpfile, prevfile);
1643        unlink_or_warn(freq->tmpfile);
1644
1645        if (freq->localfile != -1)
1646                error("fd leakage in start: %d", freq->localfile);
1647        freq->localfile = open(freq->tmpfile,
1648                               O_WRONLY | O_CREAT | O_EXCL, 0666);
1649        /*
1650         * This could have failed due to the "lazy directory creation";
1651         * try to mkdir the last path component.
1652         */
1653        if (freq->localfile < 0 && errno == ENOENT) {
1654                char *dir = strrchr(freq->tmpfile, '/');
1655                if (dir) {
1656                        *dir = 0;
1657                        mkdir(freq->tmpfile, 0777);
1658                        *dir = '/';
1659                }
1660                freq->localfile = open(freq->tmpfile,
1661                                       O_WRONLY | O_CREAT | O_EXCL, 0666);
1662        }
1663
1664        if (freq->localfile < 0) {
1665                error("Couldn't create temporary file %s: %s",
1666                      freq->tmpfile, strerror(errno));
1667                goto abort;
1668        }
1669
1670        git_inflate_init(&freq->stream);
1671
1672        git_SHA1_Init(&freq->c);
1673
1674        freq->url = get_remote_object_url(base_url, hex, 0);
1675
1676        /*
1677         * If a previous temp file is present, process what was already
1678         * fetched.
1679         */
1680        prevlocal = open(prevfile, O_RDONLY);
1681        if (prevlocal != -1) {
1682                do {
1683                        prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
1684                        if (prev_read>0) {
1685                                if (fwrite_sha1_file(prev_buf,
1686                                                     1,
1687                                                     prev_read,
1688                                                     freq) == prev_read) {
1689                                        prev_posn += prev_read;
1690                                } else {
1691                                        prev_read = -1;
1692                                }
1693                        }
1694                } while (prev_read > 0);
1695                close(prevlocal);
1696        }
1697        unlink_or_warn(prevfile);
1698
1699        /*
1700         * Reset inflate/SHA1 if there was an error reading the previous temp
1701         * file; also rewind to the beginning of the local file.
1702         */
1703        if (prev_read == -1) {
1704                memset(&freq->stream, 0, sizeof(freq->stream));
1705                git_inflate_init(&freq->stream);
1706                git_SHA1_Init(&freq->c);
1707                if (prev_posn>0) {
1708                        prev_posn = 0;
1709                        lseek(freq->localfile, 0, SEEK_SET);
1710                        if (ftruncate(freq->localfile, 0) < 0) {
1711                                error("Couldn't truncate temporary file %s: %s",
1712                                          freq->tmpfile, strerror(errno));
1713                                goto abort;
1714                        }
1715                }
1716        }
1717
1718        freq->slot = get_active_slot();
1719
1720        curl_easy_setopt(freq->slot->curl, CURLOPT_FILE, freq);
1721        curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
1722        curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr);
1723        curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url);
1724        curl_easy_setopt(freq->slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
1725
1726        /*
1727         * If we have successfully processed data from a previous fetch
1728         * attempt, only fetch the data we don't already have.
1729         */
1730        if (prev_posn>0) {
1731                if (http_is_verbose)
1732                        fprintf(stderr,
1733                                "Resuming fetch of object %s at byte %ld\n",
1734                                hex, prev_posn);
1735                sprintf(range, "Range: bytes=%ld-", prev_posn);
1736                range_header = curl_slist_append(range_header, range);
1737                curl_easy_setopt(freq->slot->curl,
1738                                 CURLOPT_HTTPHEADER, range_header);
1739        }
1740
1741        return freq;
1742
1743abort:
1744        free(freq->url);
1745        free(freq);
1746        return NULL;
1747}
1748
1749void process_http_object_request(struct http_object_request *freq)
1750{
1751        if (freq->slot == NULL)
1752                return;
1753        freq->curl_result = freq->slot->curl_result;
1754        freq->http_code = freq->slot->http_code;
1755        freq->slot = NULL;
1756}
1757
1758int finish_http_object_request(struct http_object_request *freq)
1759{
1760        struct stat st;
1761
1762        close(freq->localfile);
1763        freq->localfile = -1;
1764
1765        process_http_object_request(freq);
1766
1767        if (freq->http_code == 416) {
1768                warning("requested range invalid; we may already have all the data.");
1769        } else if (freq->curl_result != CURLE_OK) {
1770                if (stat(freq->tmpfile, &st) == 0)
1771                        if (st.st_size == 0)
1772                                unlink_or_warn(freq->tmpfile);
1773                return -1;
1774        }
1775
1776        git_inflate_end(&freq->stream);
1777        git_SHA1_Final(freq->real_sha1, &freq->c);
1778        if (freq->zret != Z_STREAM_END) {
1779                unlink_or_warn(freq->tmpfile);
1780                return -1;
1781        }
1782        if (hashcmp(freq->sha1, freq->real_sha1)) {
1783                unlink_or_warn(freq->tmpfile);
1784                return -1;
1785        }
1786        freq->rename =
1787                move_temp_to_file(freq->tmpfile, sha1_file_name(freq->sha1));
1788
1789        return freq->rename;
1790}
1791
1792void abort_http_object_request(struct http_object_request *freq)
1793{
1794        unlink_or_warn(freq->tmpfile);
1795
1796        release_http_object_request(freq);
1797}
1798
1799void release_http_object_request(struct http_object_request *freq)
1800{
1801        if (freq->localfile != -1) {
1802                close(freq->localfile);
1803                freq->localfile = -1;
1804        }
1805        if (freq->url != NULL) {
1806                free(freq->url);
1807                freq->url = NULL;
1808        }
1809        if (freq->slot != NULL) {
1810                freq->slot->callback_func = NULL;
1811                freq->slot->callback_data = NULL;
1812                release_active_slot(freq->slot);
1813                freq->slot = NULL;
1814        }
1815}