date.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <httpd.h>
  12. /*
  13. * print dates in the format
  14. * Wkd, DD Mon YYYY HH:MM:SS GMT
  15. * parse dates of formats
  16. * Wkd, DD Mon YYYY HH:MM:SS GMT
  17. * Weekday, DD-Mon-YY HH:MM:SS GMT
  18. * Wkd Mon ( D|DD) HH:MM:SS YYYY
  19. * plus anything similar
  20. */
  21. static char *
  22. weekdayname[7] =
  23. {
  24. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  25. };
  26. static char *
  27. wdayname[7] =
  28. {
  29. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  30. };
  31. static char *
  32. monname[12] =
  33. {
  34. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  35. };
  36. static int dateindex(char*, char**, int);
  37. static int
  38. dtolower(int c)
  39. {
  40. if(c >= 'A' && c <= 'Z')
  41. return c - 'A' + 'a';
  42. return c;
  43. }
  44. static int
  45. disalpha(int c)
  46. {
  47. return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
  48. }
  49. static int
  50. disdig(int c)
  51. {
  52. return c >= '0' && c <= '9';
  53. }
  54. int
  55. hdatefmt(Fmt *f)
  56. {
  57. Tm *tm;
  58. uint32_t t;
  59. t = va_arg(f->args, uint32_t);
  60. tm = gmtime(t);
  61. return fmtprint(f, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
  62. wdayname[tm->wday], tm->mday, monname[tm->mon], tm->year+1900,
  63. tm->hour, tm->min, tm->sec);
  64. }
  65. static char*
  66. dateword(char *date, char *buf)
  67. {
  68. char *p;
  69. int c;
  70. p = buf;
  71. while(!disalpha(c = *date) && !disdig(c) && c)
  72. date++;
  73. while(disalpha(c = *date)){
  74. if(p - buf < 30)
  75. *p++ = dtolower(c);
  76. date++;
  77. }
  78. *p = 0;
  79. return date;
  80. }
  81. static int
  82. datenum(char **d)
  83. {
  84. char *date;
  85. int c, n;
  86. date = *d;
  87. while(!disdig(c = *date) && c)
  88. date++;
  89. if(c == 0){
  90. *d = date;
  91. return -1;
  92. }
  93. n = 0;
  94. while(disdig(c = *date)){
  95. n = n * 10 + c - '0';
  96. date++;
  97. }
  98. *d = date;
  99. return n;
  100. }
  101. /*
  102. * parse a date and return the seconds since the epoch
  103. * return 0 for a failure
  104. */
  105. uint32_t
  106. hdate2sec(char *date)
  107. {
  108. Tm tm;
  109. char buf[32];
  110. /*
  111. * Weekday|Wday
  112. */
  113. date = dateword(date, buf);
  114. tm.wday = dateindex(buf, wdayname, 7);
  115. if(tm.wday < 0)
  116. tm.wday = dateindex(buf, weekdayname, 7);
  117. if(tm.wday < 0)
  118. return 0;
  119. /*
  120. * check for the two major formats
  121. */
  122. date = dateword(date, buf);
  123. tm.mon = dateindex(buf, monname, 12);
  124. if(tm.mon >= 0){
  125. /*
  126. * MM
  127. */
  128. tm.mday = datenum(&date);
  129. if(tm.mday < 1 || tm.mday > 31)
  130. return 0;
  131. /*
  132. * HH:MM:SS
  133. */
  134. tm.hour = datenum(&date);
  135. if(tm.hour < 0 || tm.hour >= 24)
  136. return 0;
  137. tm.min = datenum(&date);
  138. if(tm.min < 0 || tm.min >= 60)
  139. return 0;
  140. tm.sec = datenum(&date);
  141. if(tm.sec < 0 || tm.sec >= 60)
  142. return 0;
  143. /*
  144. * YYYY
  145. */
  146. tm.year = datenum(&date);
  147. if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
  148. return 0;
  149. if(tm.year >= 1970)
  150. tm.year -= 1900;
  151. }else{
  152. /*
  153. * MM-Mon-(YY|YYYY)
  154. */
  155. tm.mday = datenum(&date);
  156. if(tm.mday < 1 || tm.mday > 31)
  157. return 0;
  158. date = dateword(date, buf);
  159. tm.mon = dateindex(buf, monname, 12);
  160. if(tm.mon < 0 || tm.mon >= 12)
  161. return 0;
  162. tm.year = datenum(&date);
  163. if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
  164. return 0;
  165. if(tm.year >= 1970)
  166. tm.year -= 1900;
  167. /*
  168. * HH:MM:SS
  169. */
  170. tm.hour = datenum(&date);
  171. if(tm.hour < 0 || tm.hour >= 24)
  172. return 0;
  173. tm.min = datenum(&date);
  174. if(tm.min < 0 || tm.min >= 60)
  175. return 0;
  176. tm.sec = datenum(&date);
  177. if(tm.sec < 0 || tm.sec >= 60)
  178. return 0;
  179. /*
  180. * timezone
  181. */
  182. dateword(date, buf);
  183. if(strncmp(buf, "gmt", 3) != 0)
  184. return 0;
  185. }
  186. strcpy(tm.zone, "GMT");
  187. tm.tzoff = 0;
  188. tm.yday = 0;
  189. return tm2sec(&tm);
  190. }
  191. static int
  192. dateindex(char *d, char **tab, int n)
  193. {
  194. int i;
  195. for(i = 0; i < n; i++)
  196. if(cistrcmp(d, tab[i]) == 0)
  197. return i;
  198. return -1;
  199. }