| 927 | * curl getmoddate subcommand entry point. |
| 928 | * |
| 929 | * @param interp current interpreter |
| 930 | * @param objc number of parameters |
| 931 | * @param objv parameters |
| 932 | */ |
| 933 | int |
| 934 | CurlGetModDateCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) |
| 935 | { |
| 936 | int theResult = TCL_OK; |
| 937 | CURL* theHandle = NULL; |
| 938 | FILE* theFile = NULL; |
| 939 | |
| 940 | do { |
| 941 | int optioncrsr; |
| 942 | int lastoption; |
| 943 | int ignoresslcert = 0; |
| 944 | long theResponseCode = 0; |
| 945 | const char* theURL; |
| 946 | CURLcode theCurlCode; |
| 947 | long theModDate; |
| 948 | char theModDateString[32]; |
| 949 | |
| 950 | optioncrsr = 2; |
| 951 | lastoption = objc - 2; |
| 952 | while (optioncrsr <= lastoption) { |
| 953 | /* get the option */ |
| 954 | const char* theOption = Tcl_GetString(objv[optioncrsr]); |
| 955 | |
| 956 | if (strcmp(theOption, "--ignore-ssl-cert") == 0) { |
| 957 | ignoresslcert = 1; |
| 958 | } else { |
| 959 | Tcl_ResetResult(interp); |
| 960 | Tcl_AppendResult(interp, "curl getmoddate: unknown option ", theOption, NULL); |
| 961 | theResult = TCL_ERROR; |
| 962 | break; |
| 963 | } |
| 964 | |
| 965 | optioncrsr++; |
| 966 | } |
| 967 | |
| 968 | if (optioncrsr <= lastoption) { |
| 969 | /* something went wrong */ |
| 970 | break; |
| 971 | } |
| 972 | |
| 973 | /* first (second) parameter is the url, second (third) parameter is the date */ |
| 974 | if (objc < 3 || objc > 4) { |
| 975 | Tcl_WrongNumArgs(interp, 1, objv, "getmoddate [--ignore-ssl-cert] url date"); |
| 976 | theResult = TCL_ERROR; |
| 977 | break; |
| 978 | } |
| 979 | |
| 980 | /* Retrieve the url */ |
| 981 | theURL = Tcl_GetString(objv[objc - 1]); |
| 982 | |
| 983 | /* Open the file (dev/null) */ |
| 984 | theFile = fopen("/dev/null", "a"); |
| 985 | if (theFile == NULL) { |
| 986 | Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE); |
| 987 | theResult = TCL_ERROR; |
| 988 | break; |
| 989 | } |
| 990 | |
| 991 | /* Create the CURL handle */ |
| 992 | if (theHandle == NULL) { |
| 993 | /* Re-use existing handle if theHandle isn't NULL */ |
| 994 | theHandle = curl_easy_init(); |
| 995 | } |
| 996 | /* If we're re-using a handle, the previous call did ensure to reset it |
| 997 | * to the default state using curl_easy_reset(3) */ |
| 998 | |
| 999 | /* Setup the handle */ |
| 1000 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_URL, theURL); |
| 1001 | if (theCurlCode != CURLE_OK) { |
| 1002 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1003 | break; |
| 1004 | } |
| 1005 | |
| 1006 | /* -L option */ |
| 1007 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FOLLOWLOCATION, 1); |
| 1008 | if (theCurlCode != CURLE_OK) { |
| 1009 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1010 | break; |
| 1011 | } |
| 1012 | |
| 1013 | /* --max-redirs option, same default as curl command line */ |
| 1014 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_MAXREDIRS, 50); |
| 1015 | if (theCurlCode != CURLE_OK) { |
| 1016 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1017 | break; |
| 1018 | } |
| 1019 | |
| 1020 | /* echo any cookies received on a redirect */ |
| 1021 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_COOKIEJAR, "/dev/null"); |
| 1022 | if (theCurlCode != CURLE_OK) { |
| 1023 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1024 | break; |
| 1025 | } |
| 1026 | |
| 1027 | /* -f option */ |
| 1028 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FAILONERROR, 1); |
| 1029 | if (theCurlCode != CURLE_OK) { |
| 1030 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1031 | break; |
| 1032 | } |
| 1033 | |
| 1034 | /* set timeout on connections */ |
| 1035 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_CONNECTTIMEOUT, _CURL_CONNECTION_TIMEOUT); |
| 1036 | if (theCurlCode != CURLE_OK) { |
| 1037 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1038 | break; |
| 1039 | } |
| 1040 | |
| 1041 | /* set minimum connection speed */ |
| 1042 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_LOW_SPEED_LIMIT, _CURL_MINIMUM_XFER_SPEED); |
| 1043 | if (theCurlCode != CURLE_OK) { |
| 1044 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1045 | break; |
| 1046 | } |
| 1047 | |
| 1048 | /* set timeout interval for connections < min xfer speed */ |
| 1049 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_LOW_SPEED_TIME, _CURL_MINIMUM_XFER_TIMEOUT); |
| 1050 | if (theCurlCode != CURLE_OK) { |
| 1051 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1052 | break; |
| 1053 | } |
| 1054 | |
| 1055 | /* write to the file */ |
| 1056 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_WRITEDATA, theFile); |
| 1057 | if (theCurlCode != CURLE_OK) { |
| 1058 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1059 | break; |
| 1060 | } |
| 1061 | |
| 1062 | /* we may want to ignore ssl errors */ |
| 1063 | if (ignoresslcert) { |
| 1064 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_SSL_VERIFYPEER, (long) 0); |
| 1065 | if (theCurlCode != CURLE_OK) { |
| 1066 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1067 | break; |
| 1068 | } |
| 1069 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_SSL_VERIFYHOST, (long) 0); |
| 1070 | if (theCurlCode != CURLE_OK) { |
| 1071 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1072 | break; |
| 1073 | } |
| 1074 | } |
| 1075 | |
| 1076 | /* save the modification date */ |
| 1077 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FILETIME, 1); |
| 1078 | if (theCurlCode != CURLE_OK) { |
| 1079 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1080 | break; |
| 1081 | } |
| 1082 | |
| 1083 | /* we do not want any progress */ |
| 1084 | theCurlCode = curl_easy_setopt(theHandle, CURLOPT_NOPROGRESS, 1); |
| 1085 | if (theCurlCode != CURLE_OK) { |
| 1086 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1087 | break; |
| 1088 | } |
| 1089 | |
| 1090 | /* actually fetch the resource */ |
| 1091 | theCurlCode = curl_easy_perform(theHandle); |
| 1092 | if (theCurlCode != CURLE_OK) { |
| 1093 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1094 | break; |
| 1095 | } |
| 1096 | |
| 1097 | /* close the file */ |
| 1098 | (void) fclose(theFile); |
| 1099 | theFile = NULL; |
| 1100 | |
| 1101 | /* check everything went fine */ |
| 1102 | theCurlCode = curl_easy_getinfo(theHandle, CURLINFO_HTTP_CODE, &theResponseCode); |
| 1103 | if (theCurlCode != CURLE_OK) { |
| 1104 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1105 | break; |
| 1106 | } |
| 1107 | |
| 1108 | theModDate = 0; |
| 1109 | |
| 1110 | /* get the modification date */ |
| 1111 | theCurlCode = curl_easy_getinfo(theHandle, CURLINFO_FILETIME, &theModDate); |
| 1112 | if (theCurlCode != CURLE_OK) { |
| 1113 | theResult = SetResultFromCurlErrorCode(interp, theCurlCode); |
| 1114 | break; |
| 1115 | } |
| 1116 | |
| 1117 | (void) snprintf(theModDateString, sizeof(theModDateString), |
| 1118 | "%ld", theModDate); |
| 1119 | Tcl_SetResult(interp, theModDateString, TCL_VOLATILE); |
| 1120 | } while (0); |
| 1121 | |
| 1122 | /* reset the connection */ |
| 1123 | if (theHandle != NULL) { |
| 1124 | curl_easy_reset(theHandle); |
| 1125 | } |
| 1126 | |
| 1127 | if (theFile != NULL) { |
| 1128 | fclose(theFile); |
| 1129 | } |
| 1130 | |
| 1131 | return theResult; |
| 1132 | } |
| 1133 | |
| 1134 | /** |