synctime.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 http://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 http://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  * http://tf.nist.gov/timefreq/service/its.htm
67  * http://tf.nist.gov/timefreq/service/firewall.htm
68  *
69  * Usage:
70  * This software will synchronise your computer clock only when you issue
71  * it with --synctime. By default, it only display the webserver's clock.
72  *
73  * Written by: Frank (contributed to libcurl)
74  *
75  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
76  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
77  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
78  *
79  * IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR
80  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
81  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
82  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
83  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
84  * OF THIS SOFTWARE.
85  *
86  */
87 
88 #include <stdio.h>
89 #include <time.h>
90 #ifndef __CYGWIN__
91 #include <windows.h>
92 #endif
93 #include <curl/curl.h>
94 
95 
96 #define MAX_STRING 256
97 #define MAX_STRING1 MAX_STRING + 1
98 
99 #define SYNCTIME_UA "synctime/1.0"
100 
101 typedef struct
102 {
103  char http_proxy[MAX_STRING1];
104  char proxy_user[MAX_STRING1];
105  char timeserver[MAX_STRING1];
106 } conf_t;
107 
109 {
110  "http://pool.ntp.org/",
111  "http://nist.time.gov/",
112  "http://www.google.com/"
113 };
114 
115 const char *DayStr[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
116 const char *MthStr[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
117  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
118 
121 SYSTEMTIME SYSTime;
122 SYSTEMTIME LOCALTime;
123 
124 #define HTTP_COMMAND_HEAD 0
125 #define HTTP_COMMAND_GET 1
126 
127 
128 size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb,
129  void *stream)
130 {
131  fwrite(ptr, size, nmemb, stream);
132  return (nmemb*size);
133 }
134 
135 size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb,
136  void *stream)
137 {
138  int i, RetVal;
139  char TmpStr1[26], TmpStr2[26];
140 
141  if(ShowAllHeader == 1)
142  fprintf(stderr, "%s", (char *)(ptr));
143 
144  if(strncmp((char *)(ptr), "Date:", 5) == 0) {
145  if(ShowAllHeader == 0)
146  fprintf(stderr, "HTTP Server. %s", (char *)(ptr));
147 
148  if(AutoSyncTime == 1) {
149  *TmpStr1 = 0;
150  *TmpStr2 = 0;
151  if(strlen((char *)(ptr)) > 50) /* Can prevent buffer overflow to
152  TmpStr1 & 2? */
153  AutoSyncTime = 0;
154  else {
155  RetVal = sscanf((char *)(ptr), "Date: %s %hu %s %hu %hu:%hu:%hu",
156  TmpStr1, &SYSTime.wDay, TmpStr2, &SYSTime.wYear,
157  &SYSTime.wHour, &SYSTime.wMinute, &SYSTime.wSecond);
158 
159  if(RetVal == 7) {
160  SYSTime.wMilliseconds = 500; /* adjust to midpoint, 0.5 sec */
161  for(i = 0; i<12; i++) {
162  if(strcmp(MthStr[i], TmpStr2) == 0) {
163  SYSTime.wMonth = i + 1;
164  break;
165  }
166  }
167  AutoSyncTime = 3; /* Computer clock will be adjusted */
168  }
169  else {
170  AutoSyncTime = 0; /* Error in sscanf() fields conversion */
171  }
172  }
173  }
174  }
175 
176  if(strncmp((char *)(ptr), "X-Cache: HIT", 12) == 0) {
177  fprintf(stderr, "ERROR: HTTP Server data is cached."
178  " Server Date is no longer valid.\n");
179  AutoSyncTime = 0;
180  }
181  return (nmemb*size);
182 }
183 
184 void SyncTime_CURL_Init(CURL *curl, char *proxy_port,
185  char *proxy_user_password)
186 {
187  if(strlen(proxy_port) > 0)
188  curl_easy_setopt(curl, CURLOPT_PROXY, proxy_port);
189 
190  if(strlen(proxy_user_password) > 0)
191  curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password);
192 
193 #ifdef SYNCTIME_UA
194  curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA);
195 #endif
196  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, *SyncTime_CURL_WriteOutput);
197  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, *SyncTime_CURL_WriteHeader);
198 }
199 
200 int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName,
201  int HttpGetBody)
202 {
203  FILE *outfile;
204  CURLcode res;
205 
206  outfile = NULL;
207  if(HttpGetBody == HTTP_COMMAND_HEAD)
208  curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
209  else {
210  outfile = fopen(OutFileName, "wb");
211  curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
212  }
213 
214  curl_easy_setopt(curl, CURLOPT_URL, URL_Str);
215  res = curl_easy_perform(curl);
216  if(outfile != NULL)
217  fclose(outfile);
218  return res; /* (CURLE_OK) */
219 }
220 
221 void showUsage(void)
222 {
223  fprintf(stderr, "SYNCTIME: Synchronising computer clock with time server"
224  " using HTTP protocol.\n");
225  fprintf(stderr, "Usage : SYNCTIME [Option]\n");
226  fprintf(stderr, "Options :\n");
227  fprintf(stderr, " --server=WEBSERVER Use this time server instead"
228  " of default.\n");
229  fprintf(stderr, " --showall Show all HTTP header.\n");
230  fprintf(stderr, " --synctime Synchronising computer clock"
231  " with time server.\n");
232  fprintf(stderr, " --proxy-user=USER[:PASS] Set proxy username and"
233  " password.\n");
234  fprintf(stderr, " --proxy=HOST[:PORT] Use HTTP proxy on given"
235  " port.\n");
236  fprintf(stderr, " --help Print this help.\n");
237  fprintf(stderr, "\n");
238  return;
239 }
240 
241 int conf_init(conf_t *conf)
242 {
243  int i;
244 
245  *conf->http_proxy = 0;
246  for(i = 0; i<MAX_STRING1; i++)
247  conf->proxy_user[i] = 0; /* Clean up password from memory */
248  *conf->timeserver = 0;
249  return 1;
250 }
251 
252 int main(int argc, char *argv[])
253 {
254  CURL *curl;
255  conf_t conf[1];
256  int OptionIndex;
257  struct tm *lt;
258  struct tm *gmt;
259  time_t tt;
260  time_t tt_local;
261  time_t tt_gmt;
262  double tzonediffFloat;
263  int tzonediffWord;
264  char timeBuf[61];
265  char tzoneBuf[16];
266  int RetValue;
267 
268  OptionIndex = 0;
269  ShowAllHeader = 0; /* Do not show HTTP Header */
270  AutoSyncTime = 0; /* Do not synchronise computer clock */
271  RetValue = 0; /* Successful Exit */
272  conf_init(conf);
273 
274  if(argc > 1) {
275  while(OptionIndex < argc) {
276  if(strncmp(argv[OptionIndex], "--server=", 9) == 0)
277  snprintf(conf->timeserver, MAX_STRING, "%s", &argv[OptionIndex][9]);
278 
279  if(strcmp(argv[OptionIndex], "--showall") == 0)
280  ShowAllHeader = 1;
281 
282  if(strcmp(argv[OptionIndex], "--synctime") == 0)
283  AutoSyncTime = 1;
284 
285  if(strncmp(argv[OptionIndex], "--proxy-user=", 13) == 0)
286  snprintf(conf->proxy_user, MAX_STRING, "%s", &argv[OptionIndex][13]);
287 
288  if(strncmp(argv[OptionIndex], "--proxy=", 8) == 0)
289  snprintf(conf->http_proxy, MAX_STRING, "%s", &argv[OptionIndex][8]);
290 
291  if((strcmp(argv[OptionIndex], "--help") == 0) ||
292  (strcmp(argv[OptionIndex], "/?") == 0)) {
293  showUsage();
294  return 0;
295  }
296  OptionIndex++;
297  }
298  }
299 
300  if(*conf->timeserver == 0) /* Use default server for time information */
302 
303  /* Init CURL before usage */
305  curl = curl_easy_init();
306  if(curl) {
307  SyncTime_CURL_Init(curl, conf->http_proxy, conf->proxy_user);
308 
309  /* Calculating time diff between GMT and localtime */
310  tt = time(0);
311  lt = localtime(&tt);
312  tt_local = mktime(lt);
313  gmt = gmtime(&tt);
314  tt_gmt = mktime(gmt);
315  tzonediffFloat = difftime(tt_local, tt_gmt);
316  tzonediffWord = (int)(tzonediffFloat/3600.0);
317 
318  if((double)(tzonediffWord * 3600) == tzonediffFloat)
319  snprintf(tzoneBuf, 15, "%+03d'00'", tzonediffWord);
320  else
321  snprintf(tzoneBuf, 15, "%+03d'30'", tzonediffWord);
322 
323  /* Get current system time and local time */
324  GetSystemTime(&SYSTime);
325  GetLocalTime(&LOCALTime);
326  snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
327  DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
328  MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
329  LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
330  LOCALTime.wMilliseconds);
331 
332  fprintf(stderr, "Fetch: %s\n\n", conf->timeserver);
333  fprintf(stderr, "Before HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf);
334 
335  /* HTTP HEAD command to the Webserver */
336  SyncTime_CURL_Fetch(curl, conf->timeserver, "index.htm",
338 
339  GetLocalTime(&LOCALTime);
340  snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
341  DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
342  MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
343  LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
344  LOCALTime.wMilliseconds);
345  fprintf(stderr, "\nAfter HTTP. Date: %s%s\n", timeBuf, tzoneBuf);
346 
347  if(AutoSyncTime == 3) {
348  /* Synchronising computer clock */
349  if(!SetSystemTime(&SYSTime)) { /* Set system time */
350  fprintf(stderr, "ERROR: Unable to set system time.\n");
351  RetValue = 1;
352  }
353  else {
354  /* Successfully re-adjusted computer clock */
355  GetLocalTime(&LOCALTime);
356  snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
357  DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
358  MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
359  LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
360  LOCALTime.wMilliseconds);
361  fprintf(stderr, "\nNew System's Date: %s%s\n", timeBuf, tzoneBuf);
362  }
363  }
364 
365  /* Cleanup before exit */
366  conf_init(conf);
367  curl_easy_cleanup(curl);
368  }
369  return RetValue;
370 }
#define MAX_STRING
Definition: synctime.c:96
char timeserver[MAX_STRING1]
Definition: synctime.c:105
char http_proxy[MAX_STRING1]
Definition: synctime.c:103
#define SYNCTIME_UA
Definition: synctime.c:99
#define HTTP_COMMAND_HEAD
Definition: synctime.c:124
int ShowAllHeader
Definition: synctime.c:119
int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName, int HttpGetBody)
Definition: synctime.c:200
UNITTEST_START char * ptr
Definition: unit1330.c:38
CURLcode
Definition: curl.h:454
int AutoSyncTime
Definition: synctime.c:120
static int res
SYSTEMTIME SYSTime
Definition: synctime.c:121
#define curl_easy_setopt(handle, option, value)
Definition: typecheck-gcc.h:41
unsigned int i
Definition: unit1303.c:79
int main(int argc, char *argv[])
Definition: synctime.c:252
void SyncTime_CURL_Init(CURL *curl, char *proxy_port, char *proxy_user_password)
Definition: synctime.c:184
size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb, void *stream)
Definition: synctime.c:128
CURL_EXTERN CURL * curl_easy_init(void)
Definition: easy.c:343
const char DefaultTimeServer[3][MAX_STRING1]
Definition: synctime.c:108
const char * MthStr[]
Definition: synctime.c:116
CURL_EXTERN void curl_easy_cleanup(CURL *curl)
int conf_init(conf_t *conf)
Definition: synctime.c:241
const char * DayStr[]
Definition: synctime.c:115
void showUsage(void)
Definition: synctime.c:221
char proxy_user[MAX_STRING1]
Definition: synctime.c:104
#define MAX_STRING1
Definition: synctime.c:97
CURL_EXTERN CURLcode curl_global_init(long flags)
curl_global_init() globally initializes curl given a bitwise set of the different features of what to...
Definition: easy.c:271
size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb, void *stream)
Definition: synctime.c:135
void CURL
Definition: curl.h:102
SYSTEMTIME LOCALTime
Definition: synctime.c:122
size_t size
Definition: unit1302.c:52
#define fprintf
Definition: curl_printf.h:41
#define snprintf
Definition: curl_printf.h:42
#define CURL_GLOBAL_ALL
Definition: curl.h:2519
static CURL * curl
Definition: sessioninfo.c:35
size_t fwrite(const void *, size_t, size_t, FILE *)
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl)


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16