1 /*
2 ** Copyright 2002, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "libmail_config.h"
7 #include "mboxread.H"
8 #include "mboxmagictag.H"
9 #include "file.H"
10 
11 #include <ctype.h>
12 #include <errno.h>
13 
14 using namespace std;
15 
GenericReadTask(mail::mbox & mboxAccount,mail::callback::message & callbackArg,string uidArg,size_t messageNumberArg,bool peekArg,mail::readMode readTypeArg)16 mail::mbox::GenericReadTask::GenericReadTask(mail::mbox &mboxAccount,
17 					     mail::callback::message
18 					     &callbackArg,
19 					     string uidArg,
20 					     size_t messageNumberArg,
21 					     bool peekArg,
22 					     mail::readMode
23 					     readTypeArg)
24 	: LockTask(mboxAccount, callbackArg),
25 	  callback(callbackArg),
26 	  uid(uidArg),
27 	  messageNumber(messageNumberArg),
28 	  peek(peekArg),
29 	  readType(readTypeArg)
30 {
31 }
32 
~GenericReadTask()33 mail::mbox::GenericReadTask::~GenericReadTask()
34 {
35 }
36 
locked(mail::file & file)37 bool mail::mbox::GenericReadTask::locked(mail::file &file)
38 {
39 	if (!mboxAccount.verifyUid(uid, messageNumber, callback))
40 	{
41 		done();
42 		return true;
43 	}
44 
45 	mail::ptr<mail::mbox> me= &mboxAccount;
46 
47 	off_t p=mboxAccount.folderMessageIndex[mboxAccount.uidmap.find(uid)->second]
48 		.startingPos;
49 
50 	if (fseek(file, p, SEEK_SET) < 0)
51 	{
52 		fail(strerror(errno));
53 		return true;
54 	}
55 
56 	bool firstLine=true;
57 	bool inHeaders=true;
58 
59 	string header="";
60 
61 	while (!feof(file) && !me.isDestroyed())
62 	{
63 		string line=file.getline();
64 
65 		if (line.size() == 0 && feof(file))
66 			break;
67 
68 		if (strncmp(line.c_str(), "From ", 5) == 0)
69 		{
70 			if (firstLine)
71 				continue;
72 
73 			break;
74 		}
75 
76 		if (firstLine)
77 		{
78 			firstLine=false;
79 
80 			if (mail::mboxMagicTag(line,
81 					       mboxAccount.keywordHashtable)
82 			    .good())
83 				continue; // Ignore the magic tag line
84 		}
85 
86 		if (inHeaders)
87 		{
88 			if (line.size() == 0)
89 				inHeaders=false;
90 
91 			if (readType == mail::readHeadersFolded)
92 			{
93 				const char *p=line.c_str();
94 
95 				if (line.size() > 0 &&
96 				    unicode_isspace((unsigned char)*p))
97 				{
98 					while (unicode_isspace((unsigned char)*p))
99 						p++;
100 
101 					header += " ";
102 					header += p;
103 					continue;
104 				}
105 
106 				if (header.size() > 0)
107 				{
108 					header += "\n";
109 					callback.messageTextCallback(messageNumber,
110 								     header);
111 				}
112 				header=line;
113 				continue;
114 			}
115 
116 			line += "\n";
117 			callback.messageTextCallback(messageNumber, line);
118 			continue;
119 		}
120 
121 		if (readType != mail::readBoth &&
122 		    readType != mail::readContents)
123 		{
124 			header="";
125 			break;
126 		}
127 
128 		line += "\n";
129 
130 		const char *p=line.c_str();
131 
132 		if (*p == '>')
133 		{
134 			while (*p == '>')
135 				p++;
136 
137 			if (strncmp(p, "From ", 5) == 0)
138 				line=line.substr(1);
139 			// Dequote a >From_ line.
140 		}
141 
142 		callback.messageTextCallback(messageNumber, line);
143 	}
144 
145 	if (header.size() > 0) // Only headers, something got left over.
146 	{
147 		header += "\n";
148 		callback.messageTextCallback(messageNumber, header);
149 	}
150 
151 	if (!me.isDestroyed() && !peek &&
152 	       mboxAccount.index[messageNumber].unread)
153 	{
154 		mboxAccount.index[messageNumber].unread=false;
155 		mboxAccount.folderDirty=true;
156 		if (mboxAccount.currentFolderCallback)
157 			mboxAccount.currentFolderCallback
158 				->messageChanged(messageNumber);
159 	}
160 
161 
162 	callback.success("Folder locked.");
163 	done();
164 	return true;
165 }
166