Updated Changelog
[centerim.git] / src / icqhist.cc
blob32d55e20f72b565e0da83bd0829ce156e8cb6dc9
1 /*
3 * centerim messages history handling class
4 * $Id: icqhist.cc,v 1.15 2002/11/22 19:11:53 konst Exp $
6 * Copyright (C) 2001,2002 by Konstantin Klyagin <k@thekonst.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
25 #include "icqhist.h"
26 #include "icqcontact.h"
27 #include "icqcontacts.h"
28 #include "icqconf.h"
30 icqhistory::icqhistory() {
33 icqhistory::~icqhistory() {
36 FILE *icqhistory::open(const imcontact cinfo, const char *mode) {
37 icqcontact *c = clist.get(cinfo);
39 if(!c) {
40 if(conf.getantispam()) return 0;
41 c = clist.addnew(cinfo);
44 string fname = c->getdirname() + "/history";
46 return fopen(fname.c_str(), mode);
49 void icqhistory::putmessage(const imcontact cinfo, const string text,
50 int dir, struct tm *timestamp) {
51 FILE *f = open(cinfo, "a");
52 if(f) {
53 fprintf(f, "\f\n");
54 fprintf(f, "%s\nMSG\n", dir == HIST_MSG_OUT ? "OUT" : "IN");
55 fprintf(f, "%lu\n%lu\n%s\n", mktime(timestamp), time(0), text.c_str());
56 fclose(f);
60 void icqhistory::puturl(const imcontact cinfo, const string url,
61 const string desc, int dir, struct tm *timestamp) {
62 FILE *f = open(cinfo, "a");
63 if(f) {
64 fprintf(f, "\f\n");
65 fprintf(f, "%s\nURL\n", dir == HIST_MSG_OUT ? "OUT" : "IN");
66 fprintf(f, "%lu\n%lu\n%s\n%s\n", mktime(timestamp), time(0), url.c_str(), desc.c_str());
67 fclose(f);
71 void icqhistory::putfile(const imcontact cinfo, unsigned long seq,
72 const string fname, int fsize, int dir, struct tm *timestamp) {
73 FILE *f = open(cinfo, "a");
74 if(f) {
75 fprintf(f, "\f\n");
76 fprintf(f, "%s\nFILE\n", dir == HIST_MSG_OUT ? "OUT" : "IN");
77 fprintf(f, "%lu\n%lu\n", mktime(timestamp), time(0));
78 fprintf(f, "%lu\n%s\n%lu\n", seq, fname.c_str(), fsize);
79 fclose(f);
83 void icqhistory::putmail(const string nick, const string email,
84 const string msg, int mailt, struct tm *timestamp) {
87 bool icqhistory::opencontact(const imcontact cinfo, time_t lastread) {
88 bool ret = true;
89 FILE *f;
91 if(f = open(cinfo, "r")) {
92 opens.push_back(storedopen(f));
93 } else {
94 ret = false;
97 return ret;
100 int icqhistory::setpos(int n) {
101 char buf[512];
102 vector<storedopen>::iterator so = opens.end()-1;
104 rewind(so->f);
105 so->rn = 0;
107 if(n)
108 while(!feof(so->f)) {
109 freads(so->f, buf, 512);
111 if(!strcmp(buf, "\f")) {
112 if(++so->rn == n) {
113 break;
118 return so->rn;
121 int icqhistory::setposlastread(time_t lr) {
122 int ml = 0, fpos;
123 char buf[512];
124 bool finished;
125 vector<storedopen>::iterator so = opens.end()-1;
127 for(so->rn = 0, rewind(so->f), finished = false; !feof(so->f) && !finished; ) {
128 freads(so->f, buf, 512);
130 if(!strcmp(buf, "\f")) {
131 ml = 0;
132 fpos = ftell(so->f);
133 so->rn++;
134 } else switch(ml) {
135 case 4:
136 if(strtoul(buf, 0, 0) > lr) {
137 fseek(so->f, fpos, SEEK_SET);
138 finished = true;
140 break;
143 ml++;
146 return so->rn;
149 int icqhistory::find(const string sub, int pos) {
150 int evt, dir, n, lastfound = -1;
151 time_t lr;
152 struct tm tsent;
153 string text, url;
155 setpos(0);
157 while(((n = readevent(evt, lr, tsent, dir)) != -1) && (n < pos)) {
158 switch(evt) {
159 case EVT_MSG:
160 getmessage(text);
161 break;
162 case EVT_URL:
163 geturl(url, text);
164 text += " " + url;
165 break;
168 if(text.find(sub) != -1) lastfound = n;
171 return lastfound;
174 int icqhistory::readevent(int &event, time_t &lastread, struct tm &sent, int &dir) {
175 int ml = 1, thisevent, thisdir;
176 char buf[512];
177 bool finished, mread = false;
178 time_t t;
179 struct tm tm;
180 vector<storedopen>::iterator so = opens.end()-1;
182 so->lastevent.clear();
184 for(finished = false; !feof(so->f) && !finished; ) {
185 freads(so->f, buf, 512);
187 if(!strcmp(buf, "\f")) {
188 ml = 0;
189 if(mread) {
190 finished = true;
191 } else {
192 so->lastevent.clear();
194 } else switch(ml) {
195 case 1:
196 if(!strcmp(buf, "IN")) thisdir = HIST_MSG_IN; else
197 if(!strcmp(buf, "OUT")) thisdir = HIST_MSG_OUT;
198 break;
199 case 2:
200 if(!strcmp(buf, "URL")) thisevent = EVT_URL; else
201 if(!strcmp(buf, "MSG")) thisevent = EVT_MSG;
202 break;
203 case 3:
204 memcpy(&tm, localtime(&(t = atol(buf))), sizeof(tm));
205 break;
206 case 4:
207 dir = thisdir;
208 event = thisevent;
209 memcpy(&sent, &tm, sizeof(tm));
210 lastread = atol(buf);
211 so->rn++;
212 mread = true;
213 break;
214 default:
215 if(ml > 4)
216 so->lastevent.push_back(buf);
217 break;
220 ml++;
223 return mread ? so->rn : -1;
226 void icqhistory::getmessage(string &text) {
227 vector<storedopen>::iterator so = opens.end()-1;
228 vector<string>::iterator i;
230 for(i = so->lastevent.begin(), text = ""; i != so->lastevent.end(); ++i) {
231 if(text.size()) text += "\n";
232 text += *i;
236 void icqhistory::geturl(string &url, string &text) {
237 vector<storedopen>::iterator so = opens.end()-1;
238 vector<string>::iterator i;
240 url = text = "";
242 for(i = so->lastevent.begin(); i != so->lastevent.end(); ++i)
243 if(i == so->lastevent.begin()) url = *i; else {
244 if(text.size()) text += "\n";
245 text += *i;
249 void icqhistory::getfile(unsigned long &seq, string &fname, int &fsize) {
250 vector<storedopen>::iterator so = opens.end()-1;
251 int i;
253 for(i = 0; i < so->lastevent.size(); i++)
254 switch(i) {
255 case 0: seq = strtoul(so->lastevent[i].c_str(), 0, 0); break;
256 case 1: fname = so->lastevent[i]; break;
257 case 2: fsize = atol(so->lastevent[i].c_str());
261 void icqhistory::closecontact() {
262 if(!opens.empty()) {
263 vector<storedopen>::iterator so = opens.end()-1;
264 fclose(so->f);
265 opens.erase(so);
269 void icqhistory::fillmenu(const imcontact cinfo, verticalmenu *m) {
270 int event, dir, color, i, n = 0;
271 struct tm tm;
272 string text, url;
273 time_t lastread = 0;
274 char buf[512];
276 list<histentry> hitems;
277 list<histentry>::iterator ii;
279 if(opencontact(cinfo)) {
280 while((n = readevent(event, lastread, tm, dir)) != -1) {
281 url = text = "";
283 switch(event) {
284 case EVT_MSG:
285 getmessage(text);
286 break;
287 case EVT_URL:
288 geturl(url, text);
289 text = url + " " + text;
290 break;
293 if(cinfo.empty()) text.replace(0, 1, "");
295 if(text.size()) {
296 if(text.size() > COLS) text.erase(COLS);
297 text = (string) " " + time2str(&lastread, conf.gettimestampformat(), buf) + " " + text;
298 color = dir == HIST_MSG_IN ? conf.getcolor(cp_main_text) : conf.getcolor(cp_main_highlight);
300 histentry h;
302 h.text = text;
303 h.lastread = n;
304 h.color = color;
305 hitems.push_back(h);
309 for(ii = --hitems.end(); ; ii--) {
310 m->additemf(ii->color, (void *) ii->lastread, "%s", ii->text.c_str());
311 if(ii == hitems.begin()) break;
314 closecontact();
318 int icqhistory::getpos() {
319 vector<storedopen>::iterator so = opens.end()-1;
320 return so->rn;