Fossil SCM
Phase 2, style cleanup for httpCmd and fix minor memory leak.
Commit
047b0174b7d3db8a9f966857917fe01ddcb631b7
Parent
d1b4d1b6304ab4a…
1 file changed
+35
-34
+35
-34
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -830,95 +830,96 @@ | ||
| 830 | 830 | re_free(pRe); |
| 831 | 831 | return rc; |
| 832 | 832 | } |
| 833 | 833 | |
| 834 | 834 | /* |
| 835 | -** TH command: http -async URL ?PAYLOAD? | |
| 835 | +** TH command: http -asynchronous url ?payload? | |
| 836 | 836 | ** |
| 837 | -** Do a HTTP request to specified URL. If PAYLOAD is present | |
| 838 | -** it will be POST'ed as text/plain, otherwise it's a GET | |
| 837 | +** Perform an HTTP or HTTPS request for the specified URL. If a | |
| 838 | +** payload is present, it will be interpreted as text/plain and | |
| 839 | +** the POST method will be used; otherwise, the GET method will | |
| 840 | +** be used. Currently, all requests must be asynchronous. | |
| 839 | 841 | */ |
| 840 | 842 | static int httpCmd( |
| 841 | 843 | Th_Interp *interp, |
| 842 | 844 | void *p, |
| 843 | 845 | int argc, |
| 844 | 846 | const char **argv, |
| 845 | 847 | int *argl |
| 846 | 848 | ){ |
| 847 | - int i; | |
| 848 | - const char *zSep, *type, *regexp, *params; | |
| 849 | - Blob hdr, payload; | |
| 849 | + const char *zSep, *zType, *zRegexp, *zParams; | |
| 850 | + Blob header, payload; | |
| 850 | 851 | ReCompiled *pRe = 0; |
| 851 | 852 | |
| 852 | - if( (argc>1) && strcmp(argv[1],"-async") ){ | |
| 853 | - Th_ErrorMessage(interp, "synchronous http requests not yet implemented", 0, 0); | |
| 853 | + if( argc>1 && fossil_strnicmp(argv[1], "-asynchronous\0", 14) ){ | |
| 854 | + Th_ErrorMessage(interp, | |
| 855 | + "synchronous http requests not yet implemented", 0, 0); | |
| 854 | 856 | return TH_ERROR; |
| 855 | 857 | } |
| 856 | - ++argv; | |
| 857 | - --argc; | |
| 858 | + --argc; ++argv; ++argl; /* advance to next argument */ | |
| 858 | 859 | blob_zero(&payload); |
| 859 | 860 | if( argc!=2 ){ |
| 860 | 861 | if( argc != 3 ){ |
| 861 | - return Th_WrongNumArgs(interp, "http -async url ?payload?"); | |
| 862 | + return Th_WrongNumArgs(interp, "http -asynchronous url ?payload?"); | |
| 862 | 863 | } |
| 863 | - blob_append(&payload, argv[2], -1); | |
| 864 | - type = "POST"; | |
| 864 | + blob_append(&payload, argv[2], argl[2]); | |
| 865 | + zType = "POST"; | |
| 865 | 866 | }else{ |
| 866 | - type = "GET"; | |
| 867 | + zType = "GET"; | |
| 867 | 868 | } |
| 868 | - params = strrchr(argv[1], '?'); | |
| 869 | + zParams = strrchr(argv[1], '?'); | |
| 869 | 870 | url_parse(argv[1], 0); |
| 870 | 871 | if( g.urlIsSsh || g.urlIsFile ){ |
| 871 | 872 | Th_ErrorMessage(interp, "url must be http:// or https://", 0, 0); |
| 872 | 873 | return TH_ERROR; |
| 873 | 874 | } |
| 874 | - regexp = db_get("th1-uri-regexp", 0); | |
| 875 | - if( regexp && regexp[0] ){ | |
| 876 | - const char * zErr = re_compile(&pRe, regexp, 0); | |
| 875 | + zRegexp = db_get("th1-uri-regexp", 0); | |
| 876 | + if( zRegexp && zRegexp[0] ){ | |
| 877 | + const char *zErr = re_compile(&pRe, zRegexp, 0); | |
| 877 | 878 | if( zErr ){ |
| 878 | 879 | Th_SetResult(interp, zErr, -1); |
| 879 | 880 | return TH_ERROR; |
| 880 | 881 | } |
| 881 | 882 | } |
| 882 | - if (!pRe || !re_match(pRe, (const unsigned char *)argv[1], -1) ){ | |
| 883 | + if( !re_match(pRe, (const unsigned char *)g.urlCanonical, -1) ){ | |
| 883 | 884 | Th_SetResult(interp, "url not allowed", -1); |
| 885 | + re_free(pRe); | |
| 884 | 886 | return TH_ERROR; |
| 885 | 887 | } |
| 886 | 888 | re_free(pRe); |
| 887 | 889 | if( transport_open() ){ |
| 888 | 890 | Th_ErrorMessage(interp, transport_errmsg(), 0, 0); |
| 889 | 891 | return TH_ERROR; |
| 890 | 892 | } |
| 891 | - blob_zero(&hdr); | |
| 892 | - i = strlen(g.urlPath); | |
| 893 | - if( (i>0) && (params!=argv[1]) ){ | |
| 893 | + blob_zero(&header); | |
| 894 | + if( strlen(g.urlPath)>0 && zParams!=argv[1] ){ | |
| 894 | 895 | zSep = ""; |
| 895 | 896 | }else{ |
| 896 | 897 | zSep = "/"; |
| 897 | 898 | } |
| 898 | - blob_appendf(&hdr, "%s %s%s%s HTTP/1.0\r\n", type, zSep, g.urlPath, params?params:""); | |
| 899 | + blob_appendf(&header, "%s %s%s%s HTTP/1.0\r\n", | |
| 900 | + zType, zSep, g.urlPath, zParams ? zParams : ""); | |
| 899 | 901 | if( g.urlProxyAuth ){ |
| 900 | - blob_appendf(&hdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth); | |
| 902 | + blob_appendf(&header, "Proxy-Authorization: %s\r\n", g.urlProxyAuth); | |
| 901 | 903 | } |
| 902 | 904 | if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){ |
| 903 | 905 | char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]); |
| 904 | 906 | char *zEncoded = encode64(zCredentials, -1); |
| 905 | - blob_appendf(&hdr, "Authorization: Basic %s\r\n", zEncoded); | |
| 907 | + blob_appendf(&header, "Authorization: Basic %s\r\n", zEncoded); | |
| 906 | 908 | fossil_free(zEncoded); |
| 907 | 909 | fossil_free(zCredentials); |
| 908 | 910 | } |
| 909 | - blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname); | |
| 910 | - blob_appendf(&hdr, "User-Agent: Fossil/" RELEASE_VERSION | |
| 911 | - " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); | |
| 912 | - blob_appendf(&hdr, "Content-Type: text/plain\r\n"); | |
| 913 | - blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload)); | |
| 914 | - | |
| 915 | - transport_send(&hdr); | |
| 911 | + blob_appendf(&header, "Host: %s\r\n", g.urlHostname); | |
| 912 | + blob_appendf(&header, "User-Agent: Fossil/" RELEASE_VERSION | |
| 913 | + " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); | |
| 914 | + blob_appendf(&header, "Content-Type: text/plain\r\n"); | |
| 915 | + blob_appendf(&header, "Content-Length: %d\r\n\r\n", blob_size(&payload)); | |
| 916 | + transport_send(&header); | |
| 916 | 917 | transport_send(&payload); |
| 917 | 918 | transport_close(); |
| 918 | - g.urlProtocol=0; /* Make sure the url is not re-used. */ | |
| 919 | - Th_SetResult(interp, "", -1); | |
| 919 | + g.urlProtocol = 0; /* Make sure the parsed URL is not reused. */ | |
| 920 | + Th_SetResult(interp, 0, 0); /* NOTE: Asynchronous, no results yet. */ | |
| 920 | 921 | return TH_OK; |
| 921 | 922 | } |
| 922 | 923 | |
| 923 | 924 | /* |
| 924 | 925 | ** Make sure the interpreter has been initialized. Initialize it if |
| 925 | 926 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -830,95 +830,96 @@ | |
| 830 | re_free(pRe); |
| 831 | return rc; |
| 832 | } |
| 833 | |
| 834 | /* |
| 835 | ** TH command: http -async URL ?PAYLOAD? |
| 836 | ** |
| 837 | ** Do a HTTP request to specified URL. If PAYLOAD is present |
| 838 | ** it will be POST'ed as text/plain, otherwise it's a GET |
| 839 | */ |
| 840 | static int httpCmd( |
| 841 | Th_Interp *interp, |
| 842 | void *p, |
| 843 | int argc, |
| 844 | const char **argv, |
| 845 | int *argl |
| 846 | ){ |
| 847 | int i; |
| 848 | const char *zSep, *type, *regexp, *params; |
| 849 | Blob hdr, payload; |
| 850 | ReCompiled *pRe = 0; |
| 851 | |
| 852 | if( (argc>1) && strcmp(argv[1],"-async") ){ |
| 853 | Th_ErrorMessage(interp, "synchronous http requests not yet implemented", 0, 0); |
| 854 | return TH_ERROR; |
| 855 | } |
| 856 | ++argv; |
| 857 | --argc; |
| 858 | blob_zero(&payload); |
| 859 | if( argc!=2 ){ |
| 860 | if( argc != 3 ){ |
| 861 | return Th_WrongNumArgs(interp, "http -async url ?payload?"); |
| 862 | } |
| 863 | blob_append(&payload, argv[2], -1); |
| 864 | type = "POST"; |
| 865 | }else{ |
| 866 | type = "GET"; |
| 867 | } |
| 868 | params = strrchr(argv[1], '?'); |
| 869 | url_parse(argv[1], 0); |
| 870 | if( g.urlIsSsh || g.urlIsFile ){ |
| 871 | Th_ErrorMessage(interp, "url must be http:// or https://", 0, 0); |
| 872 | return TH_ERROR; |
| 873 | } |
| 874 | regexp = db_get("th1-uri-regexp", 0); |
| 875 | if( regexp && regexp[0] ){ |
| 876 | const char * zErr = re_compile(&pRe, regexp, 0); |
| 877 | if( zErr ){ |
| 878 | Th_SetResult(interp, zErr, -1); |
| 879 | return TH_ERROR; |
| 880 | } |
| 881 | } |
| 882 | if (!pRe || !re_match(pRe, (const unsigned char *)argv[1], -1) ){ |
| 883 | Th_SetResult(interp, "url not allowed", -1); |
| 884 | return TH_ERROR; |
| 885 | } |
| 886 | re_free(pRe); |
| 887 | if( transport_open() ){ |
| 888 | Th_ErrorMessage(interp, transport_errmsg(), 0, 0); |
| 889 | return TH_ERROR; |
| 890 | } |
| 891 | blob_zero(&hdr); |
| 892 | i = strlen(g.urlPath); |
| 893 | if( (i>0) && (params!=argv[1]) ){ |
| 894 | zSep = ""; |
| 895 | }else{ |
| 896 | zSep = "/"; |
| 897 | } |
| 898 | blob_appendf(&hdr, "%s %s%s%s HTTP/1.0\r\n", type, zSep, g.urlPath, params?params:""); |
| 899 | if( g.urlProxyAuth ){ |
| 900 | blob_appendf(&hdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth); |
| 901 | } |
| 902 | if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){ |
| 903 | char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]); |
| 904 | char *zEncoded = encode64(zCredentials, -1); |
| 905 | blob_appendf(&hdr, "Authorization: Basic %s\r\n", zEncoded); |
| 906 | fossil_free(zEncoded); |
| 907 | fossil_free(zCredentials); |
| 908 | } |
| 909 | blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname); |
| 910 | blob_appendf(&hdr, "User-Agent: Fossil/" RELEASE_VERSION |
| 911 | " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); |
| 912 | blob_appendf(&hdr, "Content-Type: text/plain\r\n"); |
| 913 | blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload)); |
| 914 | |
| 915 | transport_send(&hdr); |
| 916 | transport_send(&payload); |
| 917 | transport_close(); |
| 918 | g.urlProtocol=0; /* Make sure the url is not re-used. */ |
| 919 | Th_SetResult(interp, "", -1); |
| 920 | return TH_OK; |
| 921 | } |
| 922 | |
| 923 | /* |
| 924 | ** Make sure the interpreter has been initialized. Initialize it if |
| 925 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -830,95 +830,96 @@ | |
| 830 | re_free(pRe); |
| 831 | return rc; |
| 832 | } |
| 833 | |
| 834 | /* |
| 835 | ** TH command: http -asynchronous url ?payload? |
| 836 | ** |
| 837 | ** Perform an HTTP or HTTPS request for the specified URL. If a |
| 838 | ** payload is present, it will be interpreted as text/plain and |
| 839 | ** the POST method will be used; otherwise, the GET method will |
| 840 | ** be used. Currently, all requests must be asynchronous. |
| 841 | */ |
| 842 | static int httpCmd( |
| 843 | Th_Interp *interp, |
| 844 | void *p, |
| 845 | int argc, |
| 846 | const char **argv, |
| 847 | int *argl |
| 848 | ){ |
| 849 | const char *zSep, *zType, *zRegexp, *zParams; |
| 850 | Blob header, payload; |
| 851 | ReCompiled *pRe = 0; |
| 852 | |
| 853 | if( argc>1 && fossil_strnicmp(argv[1], "-asynchronous\0", 14) ){ |
| 854 | Th_ErrorMessage(interp, |
| 855 | "synchronous http requests not yet implemented", 0, 0); |
| 856 | return TH_ERROR; |
| 857 | } |
| 858 | --argc; ++argv; ++argl; /* advance to next argument */ |
| 859 | blob_zero(&payload); |
| 860 | if( argc!=2 ){ |
| 861 | if( argc != 3 ){ |
| 862 | return Th_WrongNumArgs(interp, "http -asynchronous url ?payload?"); |
| 863 | } |
| 864 | blob_append(&payload, argv[2], argl[2]); |
| 865 | zType = "POST"; |
| 866 | }else{ |
| 867 | zType = "GET"; |
| 868 | } |
| 869 | zParams = strrchr(argv[1], '?'); |
| 870 | url_parse(argv[1], 0); |
| 871 | if( g.urlIsSsh || g.urlIsFile ){ |
| 872 | Th_ErrorMessage(interp, "url must be http:// or https://", 0, 0); |
| 873 | return TH_ERROR; |
| 874 | } |
| 875 | zRegexp = db_get("th1-uri-regexp", 0); |
| 876 | if( zRegexp && zRegexp[0] ){ |
| 877 | const char *zErr = re_compile(&pRe, zRegexp, 0); |
| 878 | if( zErr ){ |
| 879 | Th_SetResult(interp, zErr, -1); |
| 880 | return TH_ERROR; |
| 881 | } |
| 882 | } |
| 883 | if( !re_match(pRe, (const unsigned char *)g.urlCanonical, -1) ){ |
| 884 | Th_SetResult(interp, "url not allowed", -1); |
| 885 | re_free(pRe); |
| 886 | return TH_ERROR; |
| 887 | } |
| 888 | re_free(pRe); |
| 889 | if( transport_open() ){ |
| 890 | Th_ErrorMessage(interp, transport_errmsg(), 0, 0); |
| 891 | return TH_ERROR; |
| 892 | } |
| 893 | blob_zero(&header); |
| 894 | if( strlen(g.urlPath)>0 && zParams!=argv[1] ){ |
| 895 | zSep = ""; |
| 896 | }else{ |
| 897 | zSep = "/"; |
| 898 | } |
| 899 | blob_appendf(&header, "%s %s%s%s HTTP/1.0\r\n", |
| 900 | zType, zSep, g.urlPath, zParams ? zParams : ""); |
| 901 | if( g.urlProxyAuth ){ |
| 902 | blob_appendf(&header, "Proxy-Authorization: %s\r\n", g.urlProxyAuth); |
| 903 | } |
| 904 | if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){ |
| 905 | char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]); |
| 906 | char *zEncoded = encode64(zCredentials, -1); |
| 907 | blob_appendf(&header, "Authorization: Basic %s\r\n", zEncoded); |
| 908 | fossil_free(zEncoded); |
| 909 | fossil_free(zCredentials); |
| 910 | } |
| 911 | blob_appendf(&header, "Host: %s\r\n", g.urlHostname); |
| 912 | blob_appendf(&header, "User-Agent: Fossil/" RELEASE_VERSION |
| 913 | " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); |
| 914 | blob_appendf(&header, "Content-Type: text/plain\r\n"); |
| 915 | blob_appendf(&header, "Content-Length: %d\r\n\r\n", blob_size(&payload)); |
| 916 | transport_send(&header); |
| 917 | transport_send(&payload); |
| 918 | transport_close(); |
| 919 | g.urlProtocol = 0; /* Make sure the parsed URL is not reused. */ |
| 920 | Th_SetResult(interp, 0, 0); /* NOTE: Asynchronous, no results yet. */ |
| 921 | return TH_OK; |
| 922 | } |
| 923 | |
| 924 | /* |
| 925 | ** Make sure the interpreter has been initialized. Initialize it if |
| 926 |