Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/docs/examples/synctime.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*************************************************************************** | |
| 2 * _ _ ____ _ | |
| 3 * Project ___| | | | _ \| | | |
| 4 * / __| | | | |_) | | | |
| 5 * | (__| |_| | _ <| |___ | |
| 6 * \___|\___/|_| \_\_____| | |
| 7 * | |
| 8 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. | |
| 9 * | |
| 10 * This software is licensed as described in the file COPYING, which | |
| 11 * you should have received as part of this distribution. The terms | |
| 12 * are also available at https://curl.haxx.se/docs/copyright.html. | |
| 13 * | |
| 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell | |
| 15 * copies of the Software, and permit persons to whom the Software is | |
| 16 * furnished to do so, under the terms of the COPYING file. | |
| 17 * | |
| 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | |
| 19 * KIND, either express or implied. | |
| 20 * | |
| 21 ***************************************************************************/ | |
| 22 /* <DESC> | |
| 23 * Set your system time from a remote HTTP server's Date: header. | |
| 24 * </DESC> | |
| 25 */ | |
| 26 /* This example code only builds as-is on Windows. | |
| 27 * | |
| 28 * While Unix/Linux user, you do not need this software. | |
| 29 * You can achieve the same result as synctime using curl, awk and date. | |
| 30 * Set proxy as according to your network, but beware of proxy Cache-Control. | |
| 31 * | |
| 32 * To set your system clock, root access is required. | |
| 33 * # date -s "`curl -sI https://nist.time.gov/timezone.cgi?UTC/s/0 \ | |
| 34 * | awk -F': ' '/Date: / {print $2}'`" | |
| 35 * | |
| 36 * To view remote webserver date and time. | |
| 37 * $ curl -sI https://nist.time.gov/timezone.cgi?UTC/s/0 \ | |
| 38 * | awk -F': ' '/Date: / {print $2}' | |
| 39 * | |
| 40 * Synchronising your computer clock via Internet time server usually relies | |
| 41 * on DAYTIME, TIME, or NTP protocols. These protocols provide good accurate | |
| 42 * time synchronisation but it does not work very well through a | |
| 43 * firewall/proxy. Some adjustment has to be made to the firewall/proxy for | |
| 44 * these protocols to work properly. | |
| 45 * | |
| 46 * There is an indirect method. Since most webserver provide server time in | |
| 47 * their HTTP header, therefore you could synchronise your computer clock | |
| 48 * using HTTP protocol which has no problem with firewall/proxy. | |
| 49 * | |
| 50 * For this software to work, you should take note of these items. | |
| 51 * 1. Your firewall/proxy must allow your computer to surf internet. | |
| 52 * 2. Webserver system time must in sync with the NTP time server, | |
| 53 * or at least provide an accurate time keeping. | |
| 54 * 3. Webserver HTTP header does not provide the milliseconds units, | |
| 55 * so there is no way to get very accurate time. | |
| 56 * 4. This software could only provide an accuracy of +- a few seconds, | |
| 57 * as Round-Trip delay time is not taken into consideration. | |
| 58 * Compensation of network, firewall/proxy delay cannot be simply divide | |
| 59 * the Round-Trip delay time by half. | |
| 60 * 5. Win32 SetSystemTime() API will set your computer clock according to | |
| 61 * GMT/UTC time. Therefore your computer timezone must be properly set. | |
| 62 * 6. Webserver data should not be cached by the proxy server. Some | |
| 63 * webserver provide Cache-Control to prevent caching. | |
| 64 * | |
| 65 * References: | |
| 66 * https://web.archive.org/web/20100228012139/ \ | |
| 67 * tf.nist.gov/timefreq/service/its.htm | |
| 68 * https://web.archive.org/web/20100409024302/ \ | |
| 69 * tf.nist.gov/timefreq/service/firewall.htm | |
| 70 * | |
| 71 * Usage: | |
| 72 * This software will synchronise your computer clock only when you issue | |
| 73 * it with --synctime. By default, it only display the webserver's clock. | |
| 74 * | |
| 75 * Written by: Frank (contributed to libcurl) | |
| 76 * | |
| 77 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |
| 78 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |
| 79 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |
| 80 * | |
| 81 * IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR | |
| 82 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |
| 83 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
| 84 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |
| 85 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
| 86 * OF THIS SOFTWARE. | |
| 87 * | |
| 88 */ | |
| 89 | |
| 90 #include <stdio.h> | |
| 91 #include <time.h> | |
| 92 #ifndef __CYGWIN__ | |
| 93 #include <winsock2.h> | |
| 94 #include <windows.h> | |
| 95 #endif | |
| 96 #include <curl/curl.h> | |
| 97 | |
| 98 | |
| 99 #define MAX_STRING 256 | |
| 100 #define MAX_STRING1 MAX_STRING + 1 | |
| 101 | |
| 102 #define SYNCTIME_UA "synctime/1.0" | |
| 103 | |
| 104 typedef struct | |
| 105 { | |
| 106 char http_proxy[MAX_STRING1]; | |
| 107 char proxy_user[MAX_STRING1]; | |
| 108 char timeserver[MAX_STRING1]; | |
| 109 } conf_t; | |
| 110 | |
| 111 const char DefaultTimeServer[3][MAX_STRING1] = | |
| 112 { | |
| 113 "https://nist.time.gov/", | |
| 114 "https://www.google.com/" | |
| 115 }; | |
| 116 | |
| 117 const char *DayStr[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; | |
| 118 const char *MthStr[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| 119 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; | |
| 120 | |
| 121 int ShowAllHeader; | |
| 122 int AutoSyncTime; | |
| 123 SYSTEMTIME SYSTime; | |
| 124 SYSTEMTIME LOCALTime; | |
| 125 | |
| 126 #define HTTP_COMMAND_HEAD 0 | |
| 127 #define HTTP_COMMAND_GET 1 | |
| 128 | |
| 129 | |
| 130 size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb, | |
| 131 void *stream) | |
| 132 { | |
| 133 fwrite(ptr, size, nmemb, stream); | |
| 134 return (nmemb*size); | |
| 135 } | |
| 136 | |
| 137 size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb, | |
| 138 void *stream) | |
| 139 { | |
| 140 char TmpStr1[26], TmpStr2[26]; | |
| 141 | |
| 142 (void)stream; | |
| 143 | |
| 144 if(ShowAllHeader == 1) | |
| 145 fprintf(stderr, "%s", (char *)(ptr)); | |
| 146 | |
| 147 if(strncmp((char *)(ptr), "Date:", 5) == 0) { | |
| 148 if(ShowAllHeader == 0) | |
| 149 fprintf(stderr, "HTTP Server. %s", (char *)(ptr)); | |
| 150 | |
| 151 if(AutoSyncTime == 1) { | |
| 152 *TmpStr1 = 0; | |
| 153 *TmpStr2 = 0; | |
| 154 if(strlen((char *)(ptr)) > 50) /* Can prevent buffer overflow to | |
| 155 TmpStr1 & 2? */ | |
| 156 AutoSyncTime = 0; | |
| 157 else { | |
| 158 int RetVal = sscanf((char *)(ptr), "Date: %s %hu %s %hu %hu:%hu:%hu", | |
| 159 TmpStr1, &SYSTime.wDay, TmpStr2, &SYSTime.wYear, | |
| 160 &SYSTime.wHour, &SYSTime.wMinute, | |
| 161 &SYSTime.wSecond); | |
| 162 | |
| 163 if(RetVal == 7) { | |
| 164 int i; | |
| 165 SYSTime.wMilliseconds = 500; /* adjust to midpoint, 0.5 sec */ | |
| 166 for(i = 0; i<12; i++) { | |
| 167 if(strcmp(MthStr[i], TmpStr2) == 0) { | |
| 168 SYSTime.wMonth = i + 1; | |
| 169 break; | |
| 170 } | |
| 171 } | |
| 172 AutoSyncTime = 3; /* Computer clock will be adjusted */ | |
| 173 } | |
| 174 else { | |
| 175 AutoSyncTime = 0; /* Error in sscanf() fields conversion */ | |
| 176 } | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 if(strncmp((char *)(ptr), "X-Cache: HIT", 12) == 0) { | |
| 182 fprintf(stderr, "ERROR: HTTP Server data is cached." | |
| 183 " Server Date is no longer valid.\n"); | |
| 184 AutoSyncTime = 0; | |
| 185 } | |
| 186 return (nmemb*size); | |
| 187 } | |
| 188 | |
| 189 void SyncTime_CURL_Init(CURL *curl, char *proxy_port, | |
| 190 char *proxy_user_password) | |
| 191 { | |
| 192 if(strlen(proxy_port) > 0) | |
| 193 curl_easy_setopt(curl, CURLOPT_PROXY, proxy_port); | |
| 194 | |
| 195 if(strlen(proxy_user_password) > 0) | |
| 196 curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password); | |
| 197 | |
| 198 #ifdef SYNCTIME_UA | |
| 199 curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA); | |
| 200 #endif | |
| 201 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, *SyncTime_CURL_WriteOutput); | |
| 202 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, *SyncTime_CURL_WriteHeader); | |
| 203 } | |
| 204 | |
| 205 int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName, | |
| 206 int HttpGetBody) | |
| 207 { | |
| 208 FILE *outfile; | |
| 209 CURLcode res; | |
| 210 | |
| 211 outfile = NULL; | |
| 212 if(HttpGetBody == HTTP_COMMAND_HEAD) | |
| 213 curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); | |
| 214 else { | |
| 215 outfile = fopen(OutFileName, "wb"); | |
| 216 curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); | |
| 217 } | |
| 218 | |
| 219 curl_easy_setopt(curl, CURLOPT_URL, URL_Str); | |
| 220 res = curl_easy_perform(curl); | |
| 221 if(outfile != NULL) | |
| 222 fclose(outfile); | |
| 223 return res; /* (CURLE_OK) */ | |
| 224 } | |
| 225 | |
| 226 void showUsage(void) | |
| 227 { | |
| 228 fprintf(stderr, "SYNCTIME: Synchronising computer clock with time server" | |
| 229 " using HTTP protocol.\n"); | |
| 230 fprintf(stderr, "Usage : SYNCTIME [Option]\n"); | |
| 231 fprintf(stderr, "Options :\n"); | |
| 232 fprintf(stderr, " --server=WEBSERVER Use this time server instead" | |
| 233 " of default.\n"); | |
| 234 fprintf(stderr, " --showall Show all HTTP header.\n"); | |
| 235 fprintf(stderr, " --synctime Synchronising computer clock" | |
| 236 " with time server.\n"); | |
| 237 fprintf(stderr, " --proxy-user=USER[:PASS] Set proxy username and" | |
| 238 " password.\n"); | |
| 239 fprintf(stderr, " --proxy=HOST[:PORT] Use HTTP proxy on given" | |
| 240 " port.\n"); | |
| 241 fprintf(stderr, " --help Print this help.\n"); | |
| 242 fprintf(stderr, "\n"); | |
| 243 return; | |
| 244 } | |
| 245 | |
| 246 int conf_init(conf_t *conf) | |
| 247 { | |
| 248 int i; | |
| 249 | |
| 250 *conf->http_proxy = 0; | |
| 251 for(i = 0; i<MAX_STRING1; i++) | |
| 252 conf->proxy_user[i] = 0; /* Clean up password from memory */ | |
| 253 *conf->timeserver = 0; | |
| 254 return 1; | |
| 255 } | |
| 256 | |
| 257 int main(int argc, char *argv[]) | |
| 258 { | |
| 259 CURL *curl; | |
| 260 conf_t conf[1]; | |
| 261 int RetValue; | |
| 262 | |
| 263 ShowAllHeader = 0; /* Do not show HTTP Header */ | |
| 264 AutoSyncTime = 0; /* Do not synchronise computer clock */ | |
| 265 RetValue = 0; /* Successful Exit */ | |
| 266 conf_init(conf); | |
| 267 | |
| 268 if(argc > 1) { | |
| 269 int OptionIndex = 0; | |
| 270 while(OptionIndex < argc) { | |
| 271 if(strncmp(argv[OptionIndex], "--server=", 9) == 0) | |
| 272 snprintf(conf->timeserver, MAX_STRING, "%s", &argv[OptionIndex][9]); | |
| 273 | |
| 274 if(strcmp(argv[OptionIndex], "--showall") == 0) | |
| 275 ShowAllHeader = 1; | |
| 276 | |
| 277 if(strcmp(argv[OptionIndex], "--synctime") == 0) | |
| 278 AutoSyncTime = 1; | |
| 279 | |
| 280 if(strncmp(argv[OptionIndex], "--proxy-user=", 13) == 0) | |
| 281 snprintf(conf->proxy_user, MAX_STRING, "%s", &argv[OptionIndex][13]); | |
| 282 | |
| 283 if(strncmp(argv[OptionIndex], "--proxy=", 8) == 0) | |
| 284 snprintf(conf->http_proxy, MAX_STRING, "%s", &argv[OptionIndex][8]); | |
| 285 | |
| 286 if((strcmp(argv[OptionIndex], "--help") == 0) || | |
| 287 (strcmp(argv[OptionIndex], "/?") == 0)) { | |
| 288 showUsage(); | |
| 289 return 0; | |
| 290 } | |
| 291 OptionIndex++; | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 if(*conf->timeserver == 0) /* Use default server for time information */ | |
| 296 snprintf(conf->timeserver, MAX_STRING, "%s", DefaultTimeServer[0]); | |
| 297 | |
| 298 /* Init CURL before usage */ | |
| 299 curl_global_init(CURL_GLOBAL_ALL); | |
| 300 curl = curl_easy_init(); | |
| 301 if(curl) { | |
| 302 struct tm *lt; | |
| 303 struct tm *gmt; | |
| 304 time_t tt; | |
| 305 time_t tt_local; | |
| 306 time_t tt_gmt; | |
| 307 double tzonediffFloat; | |
| 308 int tzonediffWord; | |
| 309 char timeBuf[61]; | |
| 310 char tzoneBuf[16]; | |
| 311 | |
| 312 SyncTime_CURL_Init(curl, conf->http_proxy, conf->proxy_user); | |
| 313 | |
| 314 /* Calculating time diff between GMT and localtime */ | |
| 315 tt = time(0); | |
| 316 lt = localtime(&tt); | |
| 317 tt_local = mktime(lt); | |
| 318 gmt = gmtime(&tt); | |
| 319 tt_gmt = mktime(gmt); | |
| 320 tzonediffFloat = difftime(tt_local, tt_gmt); | |
| 321 tzonediffWord = (int)(tzonediffFloat/3600.0); | |
| 322 | |
| 323 if((double)(tzonediffWord * 3600) == tzonediffFloat) | |
| 324 snprintf(tzoneBuf, 15, "%+03d'00'", tzonediffWord); | |
| 325 else | |
| 326 snprintf(tzoneBuf, 15, "%+03d'30'", tzonediffWord); | |
| 327 | |
| 328 /* Get current system time and local time */ | |
| 329 GetSystemTime(&SYSTime); | |
| 330 GetLocalTime(&LOCALTime); | |
| 331 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", | |
| 332 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, | |
| 333 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, | |
| 334 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, | |
| 335 LOCALTime.wMilliseconds); | |
| 336 | |
| 337 fprintf(stderr, "Fetch: %s\n\n", conf->timeserver); | |
| 338 fprintf(stderr, "Before HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf); | |
| 339 | |
| 340 /* HTTP HEAD command to the Webserver */ | |
| 341 SyncTime_CURL_Fetch(curl, conf->timeserver, "index.htm", | |
| 342 HTTP_COMMAND_HEAD); | |
| 343 | |
| 344 GetLocalTime(&LOCALTime); | |
| 345 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", | |
| 346 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, | |
| 347 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, | |
| 348 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, | |
| 349 LOCALTime.wMilliseconds); | |
| 350 fprintf(stderr, "\nAfter HTTP. Date: %s%s\n", timeBuf, tzoneBuf); | |
| 351 | |
| 352 if(AutoSyncTime == 3) { | |
| 353 /* Synchronising computer clock */ | |
| 354 if(!SetSystemTime(&SYSTime)) { /* Set system time */ | |
| 355 fprintf(stderr, "ERROR: Unable to set system time.\n"); | |
| 356 RetValue = 1; | |
| 357 } | |
| 358 else { | |
| 359 /* Successfully re-adjusted computer clock */ | |
| 360 GetLocalTime(&LOCALTime); | |
| 361 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", | |
| 362 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, | |
| 363 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, | |
| 364 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, | |
| 365 LOCALTime.wMilliseconds); | |
| 366 fprintf(stderr, "\nNew System's Date: %s%s\n", timeBuf, tzoneBuf); | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 /* Cleanup before exit */ | |
| 371 conf_init(conf); | |
| 372 curl_easy_cleanup(curl); | |
| 373 } | |
| 374 return RetValue; | |
| 375 } |
