aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/basetypes/MCLibetpan.cpp
blob: 918061104e04139556d15e31aa683b9f2f088b6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
//
//  MCLibetpan.cpp
//  mailcore2
//
//  Created by Hoa Dinh on 6/28/13.
//  Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCWin32.h" // should be included first.

#include "MCLibetpan.h"

#include <libetpan/libetpan.h>

#include "MCDefines.h"

using namespace mailcore;

static int tmcomp(struct tm * atmp, struct tm * btmp);

INITIALIZE(Libetpan)
{
    // It will enable CFStream on platforms that supports it.
    mailstream_cfstream_enabled = 1;
}

time_t mailcore::timestampFromDate(struct mailimf_date_time * date_time)
{
    struct tm tmval;
    time_t timeval;
    int zone_min;
    int zone_hour;
    
    tmval.tm_sec  = date_time->dt_sec;
    tmval.tm_min  = date_time->dt_min;
    tmval.tm_hour = date_time->dt_hour;
    tmval.tm_mday = date_time->dt_day;
    tmval.tm_mon  = date_time->dt_month - 1;
    if (date_time->dt_year < 1000) {
        // workaround when century is not given in year
        tmval.tm_year = date_time->dt_year + 2000 - 1900;
    }
    else {
        tmval.tm_year = date_time->dt_year - 1900;
    }
    
    timeval = mkgmtime(&tmval);
    
    if (date_time->dt_zone >= 0) {
        zone_hour = date_time->dt_zone / 100;
        zone_min = date_time->dt_zone % 100;
    }
    else {
        zone_hour = -((- date_time->dt_zone) / 100);
        zone_min = -((- date_time->dt_zone) % 100);
    }
    timeval -= zone_hour * 3600 + zone_min * 60;
    
    return timeval;
}

struct mailimf_date_time * mailcore::dateFromTimestamp(time_t timeval)
{
    struct tm gmt;
    struct tm lt;
    int off;
    struct mailimf_date_time * date_time;
    int sign;
    int hour;
    int min;
    
    gmtime_r(&timeval, &gmt);
    localtime_r(&timeval, &lt);
    
    off = (int) ((mkgmtime(&lt) - mkgmtime(&gmt)) / 60);
    if (off < 0) {
        sign = -1;
    }
    else {
        sign = 1;
    }
    off = off * sign;
    min = off % 60;
    hour = off / 60;
    off = hour * 100 + min;
    off = off * sign;
    
    date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1,
                                      lt.tm_year + 1900,
                                      lt.tm_hour, lt.tm_min, lt.tm_sec,
                                      off);
    
    return date_time;
}

struct mailimap_date_time * mailcore::imapDateFromTimestamp(time_t timeval)
{
    struct tm gmt;
    struct tm lt;
    int off;
    struct mailimap_date_time * date_time;
    int sign;
    int hour;
    int min;
    
    gmtime_r(&timeval, &gmt);
    localtime_r(&timeval, &lt);
    
    off = (int) ((mkgmtime(&lt) - mkgmtime(&gmt)) / 60);
    if (off < 0) {
        sign = -1;
    }
    else {
        sign = 1;
    }
    off = off * sign;
    min = off % 60;
    hour = off / 60;
    off = hour * 100 + min;
    off = off * sign;
    
    date_time = mailimap_date_time_new(lt.tm_mday, lt.tm_mon + 1,
                                       lt.tm_year + 1900,
                                       lt.tm_hour, lt.tm_min, lt.tm_sec,
                                       off);
    
    return date_time;
}

time_t mailcore::timestampFromIMAPDate(struct mailimap_date_time * date_time)
{
    struct tm tmval;
    time_t timeval;
    int zone_min;
    int zone_hour;
    
    tmval.tm_sec  = date_time->dt_sec;
    tmval.tm_min  = date_time->dt_min;
    tmval.tm_hour = date_time->dt_hour;
    tmval.tm_mday = date_time->dt_day;
    tmval.tm_mon  = date_time->dt_month - 1;
    if (date_time->dt_year < 1000) {
        // workaround when century is not given in year
        tmval.tm_year = date_time->dt_year + 2000 - 1900;
    }
    else {
        tmval.tm_year = date_time->dt_year - 1900;
    }
    
    timeval = mkgmtime(&tmval);
    
    if (date_time->dt_zone >= 0) {
        zone_hour = date_time->dt_zone / 100;
        zone_min = date_time->dt_zone % 100;
    }
    else {
        zone_hour = -((- date_time->dt_zone) / 100);
        zone_min = -((- date_time->dt_zone) % 100);
    }
    timeval -= zone_hour * 3600 + zone_min * 60;
    
    return timeval;
}

#define INVALID_TIMESTAMP    (-1)

static int tmcomp(struct tm * atmp, struct tm * btmp)
{
    int    result;
    
    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
        (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
        (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
        (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
        (result = (atmp->tm_min - btmp->tm_min)) == 0)
        result = atmp->tm_sec - btmp->tm_sec;
    return result;
}

time_t mailcore::mkgmtime(struct tm * tmp)
{
    int            dir;
    int            bits;
    int            saved_seconds;
    time_t                t;
    struct tm            yourtm, mytm;
    
    yourtm = *tmp;
    saved_seconds = yourtm.tm_sec;
    yourtm.tm_sec = 0;
    /*
     ** Calculate the number of magnitude bits in a time_t
     ** (this works regardless of whether time_t is
     ** signed or unsigned, though lint complains if unsigned).
     */
    for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
        ;
    /*
     ** If time_t is signed, then 0 is the median value,
     ** if time_t is unsigned, then 1 << bits is median.
     */
    if(bits > 40) bits = 40;
    t = (t < 0) ? 0 : ((time_t) 1 << bits);
    for ( ; ; ) {
        gmtime_r(&t, &mytm);
        dir = tmcomp(&mytm, &yourtm);
        if (dir != 0) {
            if (bits-- < 0) {
                return INVALID_TIMESTAMP;
            }
            if (bits < 0)
                --t;
            else if (dir > 0)
                t -= (time_t) 1 << bits;
            else    t += (time_t) 1 << bits;
            continue;
        }
        break;
    }
    t += saved_seconds;
    return t;
}