~ubuntu-branches/ubuntu/raring/lurker/raring

« back to all changes in this revision

Viewing changes to common/MessageId.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Meurer
  • Date: 2004-09-26 16:27:51 UTC
  • Revision ID: james.westby@ubuntu.com-20040926162751-z1ohcjltv7ojtg6z
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: MessageId.cpp,v 1.8 2004/08/19 23:52:51 terpstra Exp $
 
2
 *  
 
3
 *  MessageId.cpp - Helper class for manipulating internal message ids
 
4
 *  
 
5
 *  Copyright (C) 2002 - Wesley W. Terpstra
 
6
 *  
 
7
 *  License: GPL
 
8
 *  
 
9
 *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
 
10
 *  
 
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.
 
14
 *    
 
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.
 
19
 *    
 
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
 
23
 */
 
24
 
 
25
#define _XOPEN_SOURCE 500
 
26
#define _FILE_OFFSET_BITS 64
 
27
 
 
28
#include "MessageId.h"
 
29
 
 
30
#include <cstring>
 
31
#include <cstdio>
 
32
#include <cstdlib>
 
33
 
 
34
inline int dehex(char x)
 
35
{
 
36
        if (x >= 'a' && x <= 'f') return x - 'a' + 10;
 
37
        if (x >= 'A' && x <= 'F') return x - 'A' + 10;
 
38
        return x - '0';
 
39
}
 
40
 
 
41
time_t my_timegm(struct tm* tm)
 
42
{
 
43
        static bool     initd = false;
 
44
        static time_t   delta;
 
45
        
 
46
        if (!initd)
 
47
        {       // use 'x' to calculate local time zone offset portably
 
48
                time_t x = time(0);
 
49
                time_t y = mktime(gmtime(&x));
 
50
                
 
51
                delta = x - y;
 
52
                initd = true;
 
53
        }
 
54
        
 
55
        struct tm hack = *tm;
 
56
        hack.tm_sec += delta;
 
57
        return mktime(&hack);
 
58
}
 
59
 
 
60
const unsigned int MessageId::time_len = 15;
 
61
const unsigned int MessageId::full_len = 24;
 
62
const unsigned int MessageId::raw_len = 8;
 
63
 
 
64
/** Note; the serialized time is always in UTC!
 
65
 *  
 
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.
 
68
 */
 
69
 
 
70
MessageId::MessageId(const char* str)
 
71
{
 
72
        if (strlen(str) > 14 && str[8] == '.')
 
73
        {
 
74
                struct tm t;
 
75
                memset(&t, 0, sizeof(t));
 
76
                
 
77
                t.tm_year =     (str[ 0] - '0') * 1000 +
 
78
                                (str[ 1] - '0') * 100 +
 
79
                                (str[ 2] - '0') * 10 +
 
80
                                (str[ 3] - '0')
 
81
                                - 1900;
 
82
                t.tm_mon =      (str[ 4] - '0') * 10 +
 
83
                                (str[ 5] - '0')
 
84
                                - 1;
 
85
                t.tm_mday =     (str[ 6] - '0') * 10 +
 
86
                                (str[ 7] - '0');
 
87
                t.tm_hour =     (str[ 9] - '0') * 10 +
 
88
                                (str[10] - '0');
 
89
                t.tm_min =      (str[11] - '0') * 10 +
 
90
                                (str[12] - '0');
 
91
                t.tm_sec =      (str[13] - '0') * 10 +
 
92
                                (str[14] - '0');
 
93
                
 
94
                time_t tm = my_timegm(&t);
 
95
                
 
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);
 
100
        }
 
101
        else
 
102
        {
 
103
                time_[0] = time_[1] = time_[2] = time_[3] = 0;
 
104
        }
 
105
        
 
106
        if (strlen(str) > 23 && str[15] == '.')
 
107
        {
 
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]);
 
112
        }
 
113
        else
 
114
        {
 
115
                hash_[0] = hash_[1] = hash_[2] = hash_[3] = 0;
 
116
        }
 
117
}
 
118
 
 
119
string MessageId::serialize() const
 
120
{
 
121
        char buf[26];
 
122
        
 
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]);
 
127
        
 
128
        return buf;
 
129
}
 
130
 
 
131
static inline bool is_digit(char c)
 
132
{
 
133
        return (c >= '0' && c <= '9');
 
134
}
 
135
 
 
136
static inline bool is_hex(char c)
 
137
{
 
138
        return (c >= '0' && c <= '9') ||
 
139
               (c >= 'a' && c <= 'f') ||
 
140
               (c >= 'A' && c <= 'F');
 
141
}
 
142
 
 
143
bool MessageId::is_time(const char* s)
 
144
{
 
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]) &&
 
149
                s[8] == '.' &&
 
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]);
 
153
}
 
154
 
 
155
bool MessageId::is_full(const char* s)
 
156
{
 
157
        return  is_time(s) &&
 
158
                s[15] == '.' &&
 
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]);
 
163
}