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

« back to all changes in this revision

Viewing changes to common/Summary.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: Summary.cpp,v 1.2 2004/08/24 21:52:39 terpstra Exp $
 
2
 *  
 
3
 *  Summary.cpp - Helper which can load a message given MessageId
 
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 <mimelib/message.h>
 
29
 
 
30
#include <zlib.h>
 
31
#include <unistd.h>
 
32
#include <fcntl.h>
 
33
 
 
34
#include <Keys.h> 
 
35
#include <XmlEscape.h>
 
36
 
 
37
#include <memory>
 
38
#include <cerrno>
 
39
#include <cstring>
 
40
 
 
41
#include "Summary.h"
 
42
 
 
43
using namespace std;
 
44
 
 
45
string Summary::load(Reader* r, const Config& cfg)
 
46
{
 
47
        // Use the prefix limited search
 
48
        auto_ptr<Walker> w(r->seek(LU_SUMMARY + id_.raw(), "", Forward));
 
49
        
 
50
        // This will only walk records matching this id
 
51
        int ok;
 
52
        mbox_ = "";
 
53
        while ((ok = w->advance()) != -1)
 
54
        {
 
55
                if (w->key.length() < 1 + 8 + 1)
 
56
                        return "invalid mbox entry -- way too short";
 
57
                
 
58
                // We use this for getting an unsigned value below.
 
59
                const unsigned char* k = (const unsigned char*)w->key.c_str()+1+8;
 
60
                
 
61
                // read all the values
 
62
                switch (*k)
 
63
                {
 
64
                case LU_MESSAGE_DELETED:
 
65
                        deleted_ = true;
 
66
                        break;
 
67
                        
 
68
                case LU_MESSAGE_AUTHOR_EMAIL:
 
69
                        author_email_ = w->key.substr(1+8+1, string::npos);
 
70
                        if (cfg.hide_email)
 
71
                        {
 
72
                                string::size_type x = author_email_.find('@');
 
73
                                if (x != string::npos) author_email_.resize(x);
 
74
                                if (!author_name_.length()) author_name_ = author_email_;
 
75
                                author_email_ = "";
 
76
                        }
 
77
                        break;
 
78
                        
 
79
                case LU_MESSAGE_AUTHOR_NAME:
 
80
                        if (w->key.length() > 1+8+1)
 
81
                                author_name_ = w->key.substr(1+8+1, string::npos);
 
82
                        break;
 
83
                        
 
84
                case LU_MESSAGE_SUBJECT:
 
85
                        subject_ = w->key.substr(1+8+1, string::npos);
 
86
                        break;
 
87
                        
 
88
                case LU_MESSAGE_MBOX:
 
89
                        if (w->key.length() < 1+8+1+1+12)
 
90
                                return "invalid mbox entry -- too short";
 
91
                        
 
92
                        //!!! could be more careful about corrupt dbs here
 
93
                        
 
94
                        ++k;
 
95
                        mbox_ = (const char*)k; // null terminated
 
96
                        k += mbox_.length();
 
97
                        
 
98
                        int i;
 
99
                        offset_ = 0;
 
100
                        
 
101
                        for (i = 0; i < 8; ++i)
 
102
                        {
 
103
                                offset_ <<= 8;
 
104
                                offset_ |= *++k;
 
105
                        }
 
106
                        length_ = 0;
 
107
                        for (i = 8; i < 12; ++i)
 
108
                        {
 
109
                                length_ <<= 8;
 
110
                                length_ |= *++k;
 
111
                        }
 
112
                        
 
113
                        mboxs_.insert(mbox_);
 
114
                        break;
 
115
                
 
116
                default:
 
117
                        return "unknown mbox summary control code";
 
118
                }
 
119
        }
 
120
        
 
121
        if (mbox_ == "")
 
122
                return "not in a mailbox";
 
123
        
 
124
        if (ok == -1 && errno != 0)
 
125
                return string("Walker::advance:") + strerror(errno);
 
126
        
 
127
        return "";
 
128
}
 
129
 
 
130
string Summary::message(const string& dbdir, DwMessage& message) const
 
131
{
 
132
        string name = dbdir + "/" + mbox_;
 
133
        int fd = open(name.c_str(), O_RDONLY);
 
134
        if (fd == -1)
 
135
                return name + ":open:" + strerror(errno);
 
136
        
 
137
        if (lseek(fd, offset_, SEEK_SET) != offset_)
 
138
        {
 
139
                close(fd);
 
140
                return name + ":lseek:" + strerror(errno);
 
141
        }
 
142
        
 
143
        gzFile gzf = gzdopen(fd, "rb");
 
144
        if (gzf == 0)
 
145
        {
 
146
                close(fd);
 
147
                return name + ":gzdopen:" + strerror(errno);
 
148
        }
 
149
        
 
150
        DwString str;
 
151
        char buf[8192];
 
152
        unsigned long want = length_;
 
153
        
 
154
        while (want)
 
155
        {
 
156
                long get;
 
157
                if (want < sizeof(buf))
 
158
                        get = want;
 
159
                else    get = sizeof(buf);
 
160
                
 
161
                if (gzread(gzf, buf, get) != get)
 
162
                {
 
163
                        gzclose(gzf);
 
164
                        return name + ":gzread:" + strerror(errno);
 
165
                }
 
166
                
 
167
                str.append(buf, get);
 
168
                want -= get;
 
169
        }
 
170
        
 
171
        gzclose(gzf); // also closes fd
 
172
        
 
173
        message.FromString(str);
 
174
        message.Parse();
 
175
        
 
176
        return "";
 
177
}
 
178
 
 
179
ostream& operator << (ostream& o, const Summary& s)
 
180
{
 
181
        o << "<summary>"
 
182
          << "<id>" << s.id().serialize() << "</id>"
 
183
          << "<timestamp>" << s.id().timestamp() << "</timestamp>";
 
184
        
 
185
        if (s.deleted())
 
186
                o << "<deleted/>";
 
187
        
 
188
        if (s.subject().length() > 0)
 
189
                o << "<subject>" << xmlEscape << s.subject() << "</subject>";
 
190
        
 
191
        o  << "<email";
 
192
        if (s.author_email().length() > 0)
 
193
                o << " address=\"" << xmlEscape << s.author_email() << "\"";
 
194
        if (s.author_name().length() > 0)
 
195
                o << " name=\"" << xmlEscape << s.author_name() << "\"";
 
196
        o << "/></summary>";
 
197
        
 
198
        return o;
 
199
}