↑ 1 /*
↑ 2 * This program is free software; you can redistribute it and/or modify
↑ 3 * it under the terms of the GNU General Public License as published by
↑ 4 * the Free Software Foundation; either version 2 of the License, or
↑ 5 * (at your option) any later version.
↑ 6 *
↑ 7 * This program is distributed in the hope that it will be useful,
↑ 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
↑ 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
↑ 10 * GNU Library General Public License for more details.
↑ 11 *
↑ 12 * You should have received a copy of the GNU General Public License
↑ 13 * along with this program; if not, write to the Free Software
↑ 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
↑ 15 *
↑ 16 * Copyright (C) 2005-2006 Ralf Huesing <ralf@stormbind.net>
↑ 17 *
↑ 18 */
↑ 19
↑ 20 #include "rh_string.h"
↑ 21 #include "rh_gmtime.h"
↑ 22
↑ 23 #define rh_gmtime_write_wday(tm, b) \
↑ 24 switch ((tm)->tm_wday) { \
↑ 25 case 0: RH_MEMCPY4((b), "Sun,"); break; \
↑ 26 case 1: RH_MEMCPY4((b), "Mon,"); break; \
↑ 27 case 2: RH_MEMCPY4((b), "Tue,"); break; \
↑ 28 case 3: RH_MEMCPY4((b), "Wed,"); break; \
↑ 29 case 4: RH_MEMCPY4((b), "Thu,"); break; \
↑ 30 case 5: RH_MEMCPY4((b), "Fri,"); break; \
↑ 31 case 6: RH_MEMCPY4((b), "Sat,"); break; \
↑ 32 }
↑ 33
↑ 34 #define rh_gmtime_write_mday(tm,b) \
↑ 35 { \
↑ 36 (b)[5] = '0' + ((tm)->tm_mday / 10); \
↑ 37 (b)[6] = '0' + ((tm)->tm_mday % 10); \
↑ 38 }
↑ 39
↑ 40 #define rh_gmtime_write_mon(tm, b) \
↑ 41 switch ((tm)->tm_mon) { \
↑ 42 case 0: RH_MEMCPY4(&(b)[8], "Jan "); break; \
↑ 43 case 1: RH_MEMCPY4(&(b)[8], "Feb "); break; \
↑ 44 case 2: RH_MEMCPY4(&(b)[8], "Mar "); break; \
↑ 45 case 3: RH_MEMCPY4(&(b)[8], "Apr "); break; \
↑ 46 case 4: RH_MEMCPY4(&(b)[8], "May "); break; \
↑ 47 case 5: RH_MEMCPY4(&(b)[8], "Jun "); break; \
↑ 48 case 6: RH_MEMCPY4(&(b)[8], "Jul "); break; \
↑ 49 case 7: RH_MEMCPY4(&(b)[8], "Aug "); break; \
↑ 50 case 8: RH_MEMCPY4(&(b)[8], "Sep "); break; \
↑ 51 case 9: RH_MEMCPY4(&(b)[8], "Oct "); break; \
↑ 52 case 10: RH_MEMCPY4(&(b)[8], "Nov "); break; \
↑ 53 case 11: RH_MEMCPY4(&(b)[8], "Dec "); break; \
↑ 54 }
↑ 55
↑ 56 #define rh_gmtime_write_year(tm, b) \
↑ 57 { \
↑ 58 int y = (tm)->tm_year+1900; \
↑ 59 (b)[15] = '0' + (y % 10); y /= 10; \
↑ 60 (b)[14] = '0' + (y % 10); y /= 10; \
↑ 61 (b)[13] = '0' + (y % 10); y /= 10; \
↑ 62 (b)[12] = '0' + y; \
↑ 63 }
↑ 64
↑ 65 #define rh_gmtime_write_hour(tm,b) \
↑ 66 { \
↑ 67 (b)[17] = '0' + ((tm)->tm_hour / 10); \
↑ 68 (b)[18] = '0' + ((tm)->tm_hour % 10); \
↑ 69 }
↑ 70
↑ 71 #define rh_gmtime_write_min(tm, b) \
↑ 72 { \
↑ 73 (b)[20] = '0' + ((tm)->tm_min / 10); \
↑ 74 (b)[21] = '0' + ((tm)->tm_min % 10); \
↑ 75 }
↑ 76
↑ 77 #define rh_gmtime_write_sec(tm, b) \
↑ 78 { \
↑ 79 (b)[23] = '0' + ((tm)->tm_sec / 10); \
↑ 80 (b)[24] = '0' + ((tm)->tm_sec % 10); \
↑ 81 }
↑ 82
↑ 83 #if defined(OS_WIN32) || defined(WIN32)
↑ 84 static struct tm * gmtime_r (const time_t *t, struct tm *tm)
↑ 85 {
↑ 86 struct tm *res;
↑ 87
↑ 88 res = gmtime(t);
↑ 89
↑ 90 if (res)
↑ 91 *tm = *res;
↑ 92
↑ 93 return res;
↑ 94 }
↑ 95 #endif
↑ 96
↑ 97 void rh_gmtime_init (rh_gmtime_t *gmt, time_t t)
↑ 98 {
↑ 99 if (!gmtime_r (&t, &gmt->tm))
↑100 return;
↑101
↑102 gmt->used = GMT_LEN;
↑103
↑104 rh_gmtime_write_wday(&gmt->tm, gmt->data);
↑105
↑106 RH_MEMCPY4(&gmt->data[4], " ?? ");
↑107
↑108 rh_gmtime_write_mday(&gmt->tm, gmt->data);
↑109
↑110 rh_gmtime_write_mon(&gmt->tm, gmt->data);
↑111
↑112 rh_gmtime_write_year(&gmt->tm, gmt->data);
↑113
↑114 gmt->data[16] = ' ';
↑115 rh_gmtime_write_hour(&gmt->tm, gmt->data);
↑116
↑117 RH_MEMCPY4(&gmt->data[19], ":??:");
↑118 rh_gmtime_write_min(&gmt->tm, gmt->data);
↑119 rh_gmtime_write_sec(&gmt->tm, gmt->data);
↑120
↑121 RH_MEMCPY4(&gmt->data[25], " GMT");
↑122 gmt->data[29]='\0';
↑123
↑124 gmt->t=t;
↑125 }
↑126
↑127 void rh_gmtime_update (rh_gmtime_t *gmt, time_t t)
↑128 {
↑129 struct tm tm;
↑130
↑131 if (t == gmt->t)
↑132 return;
↑133
↑134 gmt->t = t;
↑135
↑136 if (!gmtime_r (&t, &tm))
↑137 return;
↑138
↑139 if (tm.tm_wday != gmt->tm.tm_wday) {
↑140 rh_gmtime_write_wday(&tm, gmt->data);
↑141 gmt->tm.tm_wday = tm.tm_wday;
↑142 }
↑143
↑144 if (tm.tm_mday != gmt->tm.tm_mday) {
↑145 rh_gmtime_write_mday(&tm, gmt->data);
↑146 gmt->tm.tm_mday = tm.tm_mday;
↑147 }
↑148
↑149 if (tm.tm_mon != gmt->tm.tm_mon) {
↑150 rh_gmtime_write_mon(&tm, gmt->data);
↑151 gmt->tm.tm_mon = tm.tm_mon;
↑152 }
↑153
↑154 if (tm.tm_year != gmt->tm.tm_year) {
↑155 rh_gmtime_write_year(&tm, gmt->data);
↑156 gmt->tm.tm_year = tm.tm_year;
↑157 }
↑158
↑159 if (tm.tm_hour != gmt->tm.tm_hour) {
↑160 rh_gmtime_write_hour(&tm, gmt->data);
↑161 gmt->tm.tm_hour = tm.tm_hour;
↑162 }
↑163
↑164 if (tm.tm_min != gmt->tm.tm_min) {
↑165 rh_gmtime_write_min(&tm, gmt->data);
↑166 gmt->tm.tm_min = tm.tm_min;
↑167 }
↑168
↑169 if (tm.tm_sec != gmt->tm.tm_sec) {
↑170 rh_gmtime_write_sec(&tm, gmt->data);
↑171 gmt->tm.tm_sec = tm.tm_sec;
↑172 }
↑173 }
↑174
↑175 int rh_gmtime_reverse (const char *src, size_t nsrc, rh_gmtime_t *out)
↑176 {
↑177 if (nsrc != GMT_LEN)
↑178 return -1;
↑179
↑180 /*
↑181 * decode time string into a binary form for comparing
↑182 *
↑183 * 01234567890123456789012345678
↑184 * 0 1 2
↑185 *
↑186 * "Sat, 04 Nov 2006 13:19:58 GMT"
↑187 *
↑188 *
↑189 * how it works:
↑190 *
↑191 * - convert the needed parts (month, year, ..) into a struct tm
↑192 * (dont test the values of correctness)
↑193 * - call mktime() with this tm
↑194 * - generate a gmtime string with this time
↑195 * - lowercased compare the strings
↑196 * (to test if the genereted gmt matches the given)
↑197 *
↑198 */
↑199
↑200 #if 0
↑201 DEBUGLOG("current[%.*s] header_in[%.*s]",
↑202 gmtime->used, gmtime->data,
↑203 entry->value.used, entry->value.data);
↑204 #endif
↑205
↑206
↑207 /* not needed because later memcasecmp is called */
↑208 #if 0
↑209 if ( ',' != src[ 3] ||
↑210 ' ' != src[ 4] ||
↑211 ' ' != src[ 7] ||
↑212 ' ' != src[11] ||
↑213 ' ' != src[16] ||
↑214 ':' != src[19] ||
↑215 ':' != src[22] )
↑216 {
↑217 return 1;
↑218 }
↑219
↑220 if (!RH_EQUAL4((src+25)," GMT"))
↑221 return 1;
↑222 #endif
↑223 TYPE_ZERO(out);
↑224
↑225 #define DSRC(_off) (src[(_off)] - '0')
↑226
↑227 out->tm.tm_hour = DSRC(17) * 10 + DSRC(18);
↑228 out->tm.tm_min = DSRC(20) * 10 + DSRC(21);
↑229 out->tm.tm_sec = DSRC(23) * 10 + DSRC(24);
↑230
↑231 out->tm.tm_mday = DSRC(5 ) * 10 + DSRC(6);
↑232
↑233 out->tm.tm_year = (DSRC(12) * 1000 +
↑234 DSRC(13) * 100 +
↑235 DSRC(14) * 10 +
↑236 DSRC(15) * 1 ) - 1900;
↑237
↑238 #undef DSRC
↑239
↑240 /* the easy way to get the month
↑241 *
↑242 * the last character is the best one to do this
↑243 *
↑244 */
↑245 switch (src[10]) {
↑246 case 'n': case 'N':
↑247 /* "Jan " "Jun " */
↑248 if (src[9] == 'a' || src[9] == 'A')
↑249 out->tm.tm_mon = 0;
↑250 else
↑251 out->tm.tm_mon = 5;
↑252 break;
↑253 case 'b': case 'B':
↑254 /* "Feb" */
↑255 out->tm.tm_mon = 2;
↑256 break;
↑257 case 'r': case 'R':
↑258 /* "Mar " "Apr " */
↑259 if (src[9] == 'a' || src[9] == 'A')
↑260 out->tm.tm_mon = 2;
↑261 else
↑262 out->tm.tm_mon = 3;
↑263 break;
↑264 case 'y': case 'Y':
↑265 /* "May " */
↑266 out->tm.tm_mon = 4;
↑267 break;
↑268 case 'l': case 'L':
↑269 /* "Jul " */
↑270 out->tm.tm_mon = 6;
↑271 break;
↑272 case 'g': case 'G':
↑273 /* "Aug " */
↑274 out->tm.tm_mon = 7;
↑275 break;
↑276 case 'p': case 'P':
↑277 /* "Sep " */
↑278 out->tm.tm_mon = 8;
↑279 break;
↑280 case 't': case 'T':
↑281 /* "Oct " */
↑282 out->tm.tm_mon = 9;
↑283 case 'v': case 'V':
↑284 /* "Nov " */
↑285 out->tm.tm_mon = 10;
↑286 break;
↑287 case 'c': case 'C':
↑288 /* "Dec " */
↑289 out->tm.tm_mon = 11;
↑290 break;
↑291 default:
↑292 return -1;
↑293 }
↑294
↑295 out->t = mktime(&out->tm);
↑296 if ((time_t)-1 == out->t)
↑297 return -1;
↑298
↑299 rh_gmtime_write_wday(&out->tm, out->data);
↑300
↑301 RH_MEMCPY4(&out->data[4], " ?? ");
↑302
↑303 rh_gmtime_write_mday(&out->tm, out->data);
↑304 rh_gmtime_write_mon(&out->tm, out->data);
↑305 rh_gmtime_write_year(&out->tm, out->data);
↑306
↑307 out->data[16] = ' ';
↑308 rh_gmtime_write_hour(&out->tm, out->data);
↑309
↑310 RH_MEMCPY4(&out->data[19], ":??:");
↑311 rh_gmtime_write_min(&out->tm, out->data);
↑312 rh_gmtime_write_sec(&out->tm, out->data);
↑313
↑314 RH_MEMCPY4(&out->data[25], " GMT");
↑315 out->data[29]='\0';
↑316
↑317 out->used = GMT_LEN;
↑318
↑319 if (0 != rh_memcasecmp(src, out->data, GMT_LEN))
↑320 return -1;
↑321
↑322 return 0;
↑323 }
syntax highlighted by Code2HTML, v. 0.9.1