/
CStorage.prg
351 lines (237 loc) · 8.46 KB
/
CStorage.prg
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/// <include file="Internet.xml" path="doc/CStorage/*" />
CLASS CStorage
PROTECT _cPath AS STRING
PROTECT _lNoSave AS LOGIC
PROTECT _hAttFile AS PTR
PROTECT _dwCode AS DWORD
PROTECT _dwCharCount AS DWORD
PROTECT _cRest AS STRING
/// <exclude />
METHOD __CreateNewID(cFileName AS STRING) AS STRING
LOCAL cID AS STRING
LOCAL cExt AS STRING
LOCAL cName AS STRING
LOCAL dwPos AS DWORD
LOCAL cToFile AS STRING
cID := __GetFileName(cFileName)
cToFile := _cPath + cID
IF File(cToFile)
IF (dwPos := RAt2(".", cID)) > 0
cName := SubStr3(cID, 1, dwPos - 1)
cExt := SubStr2(cID, dwPos)
ELSE
cName := cFileName
cExt := NULL_STRING
ENDIF
dwPos := 1
DO WHILE TRUE
cID := cName+"~"+NTrim(dwPos)+cExt
cToFile := _cPath + cID
IF ! File(cToFile)
EXIT
ENDIF
dwPos++
ENDDO
ENDIF
RETURN cID
/// <exclude />
METHOD __StreamDecode(cData AS STRING, dwCode AS DWORD) AS STRING
LOCAL dwDecoded AS DWORD
LOCAL dwLength AS DWORD
LOCAL pBuffer AS PTR
IF dwCode == CODING_TYPE_BASE64
cData := _cRest + cData
dwLength := SLen(cData)
IF dwLength > 3
pBuffer := MemAlloc((dwLength / 4) * 3)
IF pBuffer != NULL_PTR
dwDecoded := 0
IF (dwLength := B64Decode(String2Psz(cData), pBuffer, dwLength, @dwDecoded)) > 0
_cRest := SubStr2(cData, dwLength+1)
cData := Mem2String(pBuffer, dwDecoded)
ENDIF
MemFree(pBuffer)
ENDIF
ELSE
_cRest := cData
cData := NULL_STRING
ENDIF
ELSEIF dwCode == CODING_TYPE_PRINTABLE // decoding of QP encoded attachments
cData := QPDecode(cData)
ENDIF
RETURN cData
/// <exclude />
METHOD __StreamEncode(cData AS STRING, dwCode AS DWORD) AS STRING
LOCAL dwCharCount AS DWORD
IF dwCode == CODING_TYPE_BASE64
IF ! cData == NULL_STRING
dwCharCount := _dwCharCount
cData := B64EncodeStream(cData, @dwCharCount)
_dwCharCount := dwCharCount
ENDIF
ENDIF
RETURN cData
/// <include file="Internet.xml" path="doc/CStorage.AttachmentAdd/*" />
METHOD AttachmentAdd(cFile AS STRING, dwCode := 0 AS DWORD) AS STRING
LOCAL cID AS STRING
SELF:AttachmentClose()
IF _lNoSave
RETURN NULL_STRING
ENDIF
cID := SELF:__CreateNewID(cFile)
_dwCode := dwCode
_hAttFile := FCreate(_cPath + cID, FC_NORMAL)
IF _hAttFile = F_ERROR
SELF:AttachmentClose()
cID := NULL_STRING
ENDIF
RETURN cID
/// <include file="Internet.xml" path="doc/CStorage.AttachmentClose/*" />
METHOD AttachmentClose() AS VOID STRICT
//Close the current attachmentfile
IF _hAttFile != NULL_PTR
FClose(_hAttFile)
_hAttFile := NULL_PTR
ENDIF
_dwCode := _dwCharCount := 0
_cRest := NULL_STRING
RETURN
/// <include file="Internet.xml" path="doc/CStorage.AttachmentDelete/*" />
METHOD AttachmentDelete(cID AS STRING) AS LOGIC
IF ! cID = ATTACHID_PATHFLAG
//only stored attachments will be deleted and not the originals.
IF ! (cID := SELF:AttachmentFullPath(cID)) == NULL_STRING
RETURN DeleteFile(String2Psz(cID))
ENDIF
ENDIF
RETURN TRUE
/// <include file="Internet.xml" path="doc/CStorage.AttachmentFullPath/*" />
METHOD AttachmentFullPath(cAttachID AS STRING) AS STRING STRICT
IF cAttachID = ATTACHID_PATHFLAG
RETURN SubStr2(cAttachID, 2)
ENDIF
RETURN _cPath + cAttachID
/// <include file="Internet.xml" path="doc/CStorage.AttachmentOpen/*" />
METHOD AttachmentOpen(cAttachID AS STRING, dwCode := 0 AS DWORD) AS LOGIC STRICT
//Opens an attachment file for reading
//If cAttachID is empty, cFile should contain the full path of the file
SELF:AttachmentClose()
_dwCode := dwCode
_hAttFile := FOpen(SELF:AttachmentFullPath(cAttachID), _OR(FO_SHARED, FO_READ))
IF _hAttFile = F_ERROR
SELF:AttachmentClose()
RETURN FALSE
ENDIF
RETURN TRUE
/// <include file="Internet.xml" path="doc/CStorage.AttachmentRead/*" />
METHOD AttachmentRead() AS STRING STRICT
//Read from the current attachmentfile
LOCAL ptrData AS PTR
LOCAL cData AS STRING
LOCAL nData AS DWORD
IF _hAttFile != NULL_PTR
// Note: FreadStr() depends on SetAnsi, so that is why we use FRead3()
ptrData := MemAlloc(1536)
nData := FRead3(_hAttFile, ptrData, 1536)
cData := Mem2String(ptrData, nData)
MemFree(ptrData)
RETURN SELF:__StreamEncode(cData, _dwCode)
ENDIF
RETURN NULL_STRING
/// <include file="Internet.xml" path="doc/CStorage.AttachmentSave/*" />
METHOD AttachmentSave(cAttachID AS STRING, cToFile AS STRING) AS LOGIC
//Save the attachment with the ID cAttachID to the file cToFile
//cToFile must be a full path name
//If cAttachID is empty, cFile should contain the full path name of the file
RETURN FCopy(SELF:AttachmentFullPath(cAttachID), cToFile)
/// <include file="Internet.xml" path="doc/CStorage.AttachmentSize/*" />
ACCESS AttachmentSize AS DWORD STRICT
//Calculates the size of the current opened attachment file
LOCAL dwPos , dwSize AS LONGINT
IF _hAttFile != NULL_PTR
dwPos := (LONG) FTell(_hAttFile)
dwSize := FSeek3(_hAttFile, 0, FS_END)
FSeek3(_hAttFile, LONGINT(_CAST,dwPos), FS_SET)
ENDIF
RETURN DWORD(dwSize)
/// <include file="Internet.xml" path="doc/CStorage.AttachmentWrite/*" />
METHOD AttachmentWrite(cData AS STRING) AS VOID STRICT
//Write to the current attachmentfile
IF _hAttFile != NULL_PTR
cData := SELF:__StreamDecode(cData, _dwCode)
FWrite(_hAttFile, cData, SLen(cData))
ENDIF
RETURN
/// <include file="Internet.xml" path="doc/CStorage.CreateNewEMail/*" />
METHOD CreateNewEMail() AS CEMail STRICT
RETURN CEMail{NIL, SELF}
/// <include file="Internet.xml" path="doc/CStorage.ctor/*" />
CONSTRUCTOR(cPath)
IF IsString(cPath)
_cPath := cPath
ELSE
_cPath := GetDefault()
ENDIF
IF Right(_cPath,1) != "\"
_cPath += "\"
ENDIF
RETURN
/// <include file="Internet.xml" path="doc/CStorage.LoadEMail/*" />
METHOD LoadEMail(cId AS STRING)
//Load an EMail with the ID cID into an empty CEMail object and fill the object
//You should do the following:
LOCAL oEMail AS CEMail
oEMail := SELF:CreateNewEmail()
// 1.) assign oEMail:MailHeader
// 2.) Call oEMail:GetHeaderInfo()
// 3.) assign oEMail:Body
// 4.) assign oEMail:Html
// 5.) assign oEMail:AttachmentInfo
RETURN oEMail
/// <include file="Internet.xml" path="doc/CStorage.NoSave/*" />
ASSIGN NoSave(lValue AS LOGIC)
RETURN _lNoSave := lValue
/// <include file="Internet.xml" path="doc/CStorage.RawClose/*" />
METHOD RawClose() AS VOID STRICT
RETURN
/// <include file="Internet.xml" path="doc/CStorage.RawNew/*" />
METHOD RawNew(oEMail AS CEmail) AS VOID STRICT
RETURN
/// <include file="Internet.xml" path="doc/CStorage.RawWrite/*" />
METHOD RawWrite(cData AS STRING) AS VOID STRICT
RETURN
/// <include file="Internet.xml" path="doc/CStorage.SaveAttachments/*" />
METHOD SaveAttachments(oEMail AS CEMail, lClone := FALSE AS LOGIC) AS LOGIC STRICT
LOCAL dwI AS DWORD
LOCAL dwCount AS DWORD
LOCAL cID AS STRING
LOCAL cNewID AS STRING
LOCAL cFileName AS STRING
IF oEMail != NULL_OBJECT
dwCount := oEmail:AttachmentCount
FOR dwI := 1 UPTO dwCount
cID := oEmail:GetAttachmentInfo(dwI, ATTACH_STOREID)
IF cID = ATTACHID_PATHFLAG .OR. lClone
cFileName := oEmail:GetAttachmentInfo(dwI, ATTACH_FILENAME)
cNewID := SELF:__CreateNewID(cFileName)
SELF:AttachmentSave(cID, _cPath + SELF:__CreateNewID(cFileName))
oEmail:SetAttachmentInfo(dwI, ATTACH_STOREID, cNewID)
ENDIF
NEXT // dwI
ENDIF
RETURN TRUE
/// <include file="Internet.xml" path="doc/CStorage.SaveEMail/*" />
METHOD SaveEMail(cId AS STRING, oEMail AS CEMail) AS LOGIC STRICT
//Save oEMail with the current ID
//You should save the following
// 1.) oEMail:MailHeader for received mails, for not sended mails
// call at first oEMail:SetHeaderInfo() to create the MailHeader
// 2.) oEMail:Body
// 3.) oEMail:Html
// 4.) Call first Self:SaveAttachments(oEMail) and than store
// oEMail:AttachmentInfo
RETURN TRUE
END CLASS
#region defines
DEFINE ATTACHID_PATHFLAG := ">"
#endregion