1
/* $Id: MessageId.cpp,v 1.8 2004/08/19 23:52:51 terpstra Exp $
3
* MessageId.cpp - Helper class for manipulating internal message ids
5
* Copyright (C) 2002 - Wesley W. Terpstra
9
* Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; version 2.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
#define _XOPEN_SOURCE 500
26
#define _FILE_OFFSET_BITS 64
28
#include "MessageId.h"
34
inline int dehex(char x)
36
if (x >= 'a' && x <= 'f') return x - 'a' + 10;
37
if (x >= 'A' && x <= 'F') return x - 'A' + 10;
41
time_t my_timegm(struct tm* tm)
43
static bool initd = false;
47
{ // use 'x' to calculate local time zone offset portably
49
time_t y = mktime(gmtime(&x));
60
const unsigned int MessageId::time_len = 15;
61
const unsigned int MessageId::full_len = 24;
62
const unsigned int MessageId::raw_len = 8;
64
/** Note; the serialized time is always in UTC!
66
* This is so that the same message will have the same lurker id across
67
* all servers with the message, regardless of their timezone.
70
MessageId::MessageId(const char* str)
72
if (strlen(str) > 14 && str[8] == '.')
75
memset(&t, 0, sizeof(t));
77
t.tm_year = (str[ 0] - '0') * 1000 +
78
(str[ 1] - '0') * 100 +
79
(str[ 2] - '0') * 10 +
82
t.tm_mon = (str[ 4] - '0') * 10 +
85
t.tm_mday = (str[ 6] - '0') * 10 +
87
t.tm_hour = (str[ 9] - '0') * 10 +
89
t.tm_min = (str[11] - '0') * 10 +
91
t.tm_sec = (str[13] - '0') * 10 +
94
time_t tm = my_timegm(&t);
96
time_[3] = (tm & 0xFF); tm >>= 8;
97
time_[2] = (tm & 0xFF); tm >>= 8;
98
time_[1] = (tm & 0xFF); tm >>= 8;
99
time_[0] = (tm & 0xFF);
103
time_[0] = time_[1] = time_[2] = time_[3] = 0;
106
if (strlen(str) > 23 && str[15] == '.')
108
hash_[0] = dehex(str[16]) * 16 + dehex(str[17]);
109
hash_[1] = dehex(str[18]) * 16 + dehex(str[19]);
110
hash_[2] = dehex(str[20]) * 16 + dehex(str[21]);
111
hash_[3] = dehex(str[22]) * 16 + dehex(str[23]);
115
hash_[0] = hash_[1] = hash_[2] = hash_[3] = 0;
119
string MessageId::serialize() const
123
time_t then = timestamp();
124
strftime(buf, 25, "%Y%m%d.%H%M%S", gmtime(&then));
125
snprintf(&buf[15], 10, ".%02x%02x%02x%02x",
126
hash_[0], hash_[1], hash_[2], hash_[3]);
131
static inline bool is_digit(char c)
133
return (c >= '0' && c <= '9');
136
static inline bool is_hex(char c)
138
return (c >= '0' && c <= '9') ||
139
(c >= 'a' && c <= 'f') ||
140
(c >= 'A' && c <= 'F');
143
bool MessageId::is_time(const char* s)
145
return is_digit(s[0]) && is_digit(s[1]) &&
146
is_digit(s[2]) && is_digit(s[3]) &&
147
is_digit(s[4]) && is_digit(s[5]) &&
148
is_digit(s[6]) && is_digit(s[7]) &&
150
is_digit(s[ 9]) && is_digit(s[10]) &&
151
is_digit(s[11]) && is_digit(s[12]) &&
152
is_digit(s[13]) && is_digit(s[14]);
155
bool MessageId::is_full(const char* s)
159
is_hex(s[16]) && is_hex(s[17]) &&
160
is_hex(s[18]) && is_hex(s[19]) &&
161
is_hex(s[20]) && is_hex(s[21]) &&
162
is_hex(s[22]) && is_hex(s[23]);