@@ -665,6 +665,110 @@ static char *quote_ref_url(const char *base, const char *ref)
665
665
return strbuf_detach (& buf , NULL );
666
666
}
667
667
668
+ /* http_request() targets */
669
+ #define HTTP_REQUEST_STRBUF 0
670
+ #define HTTP_REQUEST_FILE 1
671
+
672
+ static int http_request (const char * url , void * result , int target , int options )
673
+ {
674
+ struct active_request_slot * slot ;
675
+ struct slot_results results ;
676
+ struct curl_slist * headers = NULL ;
677
+ struct strbuf buf = STRBUF_INIT ;
678
+ int ret ;
679
+
680
+ slot = get_active_slot ();
681
+ slot -> results = & results ;
682
+ curl_easy_setopt (slot -> curl , CURLOPT_HTTPGET , 1 );
683
+
684
+ if (result == NULL ) {
685
+ curl_easy_setopt (slot -> curl , CURLOPT_NOBODY , 1 );
686
+ } else {
687
+ curl_easy_setopt (slot -> curl , CURLOPT_NOBODY , 0 );
688
+ curl_easy_setopt (slot -> curl , CURLOPT_FILE , result );
689
+
690
+ if (target == HTTP_REQUEST_FILE ) {
691
+ long posn = ftell (result );
692
+ curl_easy_setopt (slot -> curl , CURLOPT_WRITEFUNCTION ,
693
+ fwrite );
694
+ if (posn > 0 ) {
695
+ strbuf_addf (& buf , "Range: bytes=%ld-" , posn );
696
+ headers = curl_slist_append (headers , buf .buf );
697
+ strbuf_reset (& buf );
698
+ }
699
+ slot -> local = result ;
700
+ } else
701
+ curl_easy_setopt (slot -> curl , CURLOPT_WRITEFUNCTION ,
702
+ fwrite_buffer );
703
+ }
704
+
705
+ strbuf_addstr (& buf , "Pragma:" );
706
+ if (options & HTTP_NO_CACHE )
707
+ strbuf_addstr (& buf , " no-cache" );
708
+
709
+ headers = curl_slist_append (headers , buf .buf );
710
+
711
+ curl_easy_setopt (slot -> curl , CURLOPT_URL , url );
712
+ curl_easy_setopt (slot -> curl , CURLOPT_HTTPHEADER , headers );
713
+
714
+ if (start_active_slot (slot )) {
715
+ run_active_slot (slot );
716
+ if (results .curl_result == CURLE_OK )
717
+ ret = HTTP_OK ;
718
+ else if (missing_target (& results ))
719
+ ret = HTTP_MISSING_TARGET ;
720
+ else
721
+ ret = HTTP_ERROR ;
722
+ } else {
723
+ error ("Unable to start HTTP request for %s" , url );
724
+ ret = HTTP_START_FAILED ;
725
+ }
726
+
727
+ slot -> local = NULL ;
728
+ curl_slist_free_all (headers );
729
+ strbuf_release (& buf );
730
+
731
+ return ret ;
732
+ }
733
+
734
+ int http_get_strbuf (const char * url , struct strbuf * result , int options )
735
+ {
736
+ return http_request (url , result , HTTP_REQUEST_STRBUF , options );
737
+ }
738
+
739
+ int http_get_file (const char * url , const char * filename , int options )
740
+ {
741
+ int ret ;
742
+ struct strbuf tmpfile = STRBUF_INIT ;
743
+ FILE * result ;
744
+
745
+ strbuf_addf (& tmpfile , "%s.temp" , filename );
746
+ result = fopen (tmpfile .buf , "a" );
747
+ if (! result ) {
748
+ error ("Unable to open local file %s" , tmpfile .buf );
749
+ ret = HTTP_ERROR ;
750
+ goto cleanup ;
751
+ }
752
+
753
+ ret = http_request (url , result , HTTP_REQUEST_FILE , options );
754
+ fclose (result );
755
+
756
+ if ((ret == HTTP_OK ) && move_temp_to_file (tmpfile .buf , filename ))
757
+ ret = HTTP_ERROR ;
758
+ cleanup :
759
+ strbuf_release (& tmpfile );
760
+ return ret ;
761
+ }
762
+
763
+ int http_error (const char * url , int ret )
764
+ {
765
+ /* http_request has already handled HTTP_START_FAILED. */
766
+ if (ret != HTTP_START_FAILED )
767
+ error ("%s while accessing %s\n" , curl_errorstr , url );
768
+
769
+ return ret ;
770
+ }
771
+
668
772
int http_fetch_ref (const char * base , struct ref * ref )
669
773
{
670
774
char * url ;
0 commit comments