1 /* (c) 2003-2006 by Marcin Wiacek */
2 /* function for making CRC for filesystem (c) 2003 by Michael Schroeder */
3 
4 #include <gammu-config.h>
5 
6 #ifdef GSM_ENABLE_NOKIA6510
7 
8 #include <string.h>
9 #include <time.h>
10 
11 #include "../../../../misc/coding/coding.h"
12 #include "../../../../gsmcomon.h"
13 #include "../../../../service/gsmlogo.h"
14 #include "../../nfunc.h"
15 #include "../../nfuncold.h"
16 #include "../../../pfunc.h"
17 #include "../dct4func.h"
18 #include "n6510.h"
19 #include "../../../../../libgammu/misc/string.h"
20 
21 /* shared */
22 
23 /**
24  * Shifts data in file cache by defined count.
25  *
26  * \param move How to move entries. +10 means that i entry will become
27  * i + 10, while -10 means that entries will be moved backwards. Of
28  * course starting at the beginning of the list. So 10 entry will become 0.
29  */
N6510_ShiftFileCache(GSM_StateMachine * s,int move)30 static GSM_Error N6510_ShiftFileCache(GSM_StateMachine *s, int move)
31 {
32 	GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
33 	int i;
34 
35 	if (move < 0) {
36 		for (i = 0; i < Priv->FilesLocationsUsed + move; i++) {
37 			memcpy(&Priv->FilesCache[i], &Priv->FilesCache[i - move], sizeof(GSM_File));
38 			smprintf(s, "Copying %i to %i\n", i - move, i);
39 		}
40 	} else {
41 		for (i = Priv->FilesLocationsUsed - 1; i >= 0; i--) {
42 			memcpy(&Priv->FilesCache[i + move], &Priv->FilesCache[i], sizeof(GSM_File));
43 			smprintf(s, "Copying %i to %i\n", i, i + move);
44 		}
45 	}
46 
47 	Priv->FilesLocationsUsed += move;
48 
49 	return ERR_NONE;
50 }
51 /**
52  * Allocates enough entries in file cache.
53  *
54  * \param requested Number of files which are requested.
55  */
N6510_AllocFileCache(GSM_StateMachine * s,int requested)56 static GSM_Error N6510_AllocFileCache(GSM_StateMachine *s, int requested)
57 {
58 	GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
59 	int newsize;
60 
61 	/* Maybe there is already enough allocated */
62 	if (Priv->FilesLocationsAvail >= requested) return ERR_NONE;
63 
64 	/* Do not allocate one by one */
65 	newsize = requested + 10;
66 
67 	/* Reallocate memory */
68 	Priv->FilesCache = (GSM_File *)realloc(Priv->FilesCache, newsize * sizeof(GSM_File));
69 	if (Priv->FilesCache == NULL) return ERR_MOREMEMORY;
70 
71 	/* Store new cache size */
72 	Priv->FilesLocationsAvail = newsize;
73 
74 	return ERR_NONE;
75 }
76 
N6510_FindFileCheckSum12(GSM_StateMachine * s,unsigned char * ptr,int len)77 static int N6510_FindFileCheckSum12(GSM_StateMachine *s, unsigned char *ptr, int len)
78 {
79 	int acc, i, accx;
80 
81 	accx = 0;
82 	acc  = 0xffff;
83 	while (len--) {
84 		accx = (accx & 0xffff00ff) | (acc & 0xff00);
85 		acc  = (acc  & 0xffff00ff) | (*ptr++ << 8);
86 		for (i = 0; i < 8; i++) {
87 			acc <<= 1;
88 			if (acc & 0x10000)     acc ^= 0x1021;
89 			if (accx & 0x80000000) acc ^= 0x1021;
90 			accx <<= 1;
91 		}
92 	}
93 	smprintf(s, "Checksum from Gammu is %04X\n",(acc & 0xffff));
94 	return (acc & 0xffff);
95 }
96 
N6510_ReplyGetFilePart12(GSM_Protocol_Message * msg,GSM_StateMachine * s)97 GSM_Error N6510_ReplyGetFilePart12(GSM_Protocol_Message *msg, GSM_StateMachine *s)
98 {
99 	int old;
100 
101 	smprintf(s,"File part received\n");
102 	old = s->Phone.Data.File->Used;
103 	s->Phone.Data.File->Used += msg->Buffer[6]*256*256*256+
104 				    msg->Buffer[7]*256*256+
105 				    msg->Buffer[8]*256+
106 				    msg->Buffer[9];
107 	smprintf(s,"Length of file part: %i\n",
108 			msg->Buffer[6]*256*256*256+
109 			msg->Buffer[7]*256*256+
110 			msg->Buffer[8]*256+
111 			msg->Buffer[9]);
112 	s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
113 	memcpy(s->Phone.Data.File->Buffer+old,msg->Buffer+10,s->Phone.Data.File->Used-old);
114 	return ERR_NONE;
115 }
116 
N6510_ReplyGetFileCRC12(GSM_Protocol_Message * msg,GSM_StateMachine * s)117 GSM_Error N6510_ReplyGetFileCRC12(GSM_Protocol_Message *msg, GSM_StateMachine *s)
118 {
119 	GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
120 
121 	Priv->FileCheckSum = msg->Buffer[6] * 256 + msg->Buffer[7];
122 	smprintf(s,"File checksum from phone is %04X\n",Priv->FileCheckSum);
123 	return ERR_NONE;
124 }
125 
126 /* filesystem 1 */
127 
N6510_GetFileCRC1(GSM_StateMachine * s,unsigned char * id)128 static GSM_Error N6510_GetFileCRC1(GSM_StateMachine *s, unsigned char *id)
129 {
130 	unsigned char	   	GetCRC[] = {
131 		N7110_FRAME_HEADER, 0x42, 0x00, 0x00, 0x00, 0x01,
132 		0x00, 0x1E};    /* file ID */
133 
134 	GetCRC[8] = atoi(DecodeUnicodeString(id)) / 256;
135 	GetCRC[9] = atoi(DecodeUnicodeString(id)) % 256;
136 	smprintf(s,"Getting CRC for file in filesystem\n");
137 	return GSM_WaitFor (s, GetCRC, 10, 0x6D, 4, ID_GetCRC);
138 }
139 
N6510_ReplyGetFileFolderInfo1(GSM_Protocol_Message * msg,GSM_StateMachine * s)140 GSM_Error N6510_ReplyGetFileFolderInfo1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
141 {
142 	GSM_File		*File = s->Phone.Data.FileInfo;
143 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
144 	int		     	i, newsize;
145 	unsigned		char buffer[500];
146 	GSM_Error		error;
147 
148 	switch (msg->Buffer[3]) {
149 	case 0x15:
150 		smprintf(s,"File or folder details received\n");
151 		CopyUnicodeString(File->Name,msg->Buffer+10);
152 		if (msg->Length == 14) {
153 			smprintf(s,"File not exist\n");
154 			return ERR_FILENOTEXIST;
155 		}
156 		if (!strncmp(DecodeUnicodeString(File->Name),"GMSTemp",7)) return ERR_EMPTY;
157 		if (File->Name[0] == 0x00 && File->Name[1] == 0x00) return ERR_UNKNOWN;
158 
159 /* 		EncodeHexUnicode (buffer, File->Name, UnicodeLength(File->Name)); */
160 /* 		smprintf(s,"Name encoded: %s\n",buffer); */
161 
162 		i = msg->Buffer[8]*256+msg->Buffer[9];
163 		smprintf(s, "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
164 			msg->Buffer[i-5],msg->Buffer[i-4],msg->Buffer[i-3],
165 			msg->Buffer[i-2],msg->Buffer[i-1],msg->Buffer[i],
166 			msg->Buffer[i+1],msg->Buffer[i+2],msg->Buffer[i+3]);
167 
168 		File->Folder = FALSE;
169 		if (msg->Buffer[i-5] == 0x00 && msg->Buffer[i-3]==0x02) File->Folder = TRUE;
170 
171 		File->ReadOnly  = FALSE;
172 		File->Protected = FALSE;
173 		File->System    = FALSE;
174 		File->Hidden    = FALSE;
175 		if (msg->Buffer[i+2] == 0x01) File->Protected    = TRUE;
176 		if (msg->Buffer[i+4] == 0x01) File->ReadOnly     = TRUE;
177 		if (msg->Buffer[i+5] == 0x01) File->Hidden       = TRUE;
178 		if (msg->Buffer[i+6] == 0x01) File->System       = TRUE;/* fixme */
179 
180 		File->ModifiedEmpty = FALSE;
181 		NOKIA_DecodeDateTime(s, msg->Buffer+i-22, &File->Modified, TRUE, FALSE);
182 		if (File->Modified.Year == 0x00) File->ModifiedEmpty = TRUE;
183 		if (File->Modified.Year == 0xffff) File->ModifiedEmpty = TRUE;
184 		smprintf(s, "%02x %02x %02x %02x\n",msg->Buffer[i-22],msg->Buffer[i-21],msg->Buffer[i-20],msg->Buffer[i-19]);
185 
186 		Priv->FileToken = msg->Buffer[i-10]*256+msg->Buffer[i-9];
187 		Priv->ParentID  = msg->Buffer[i]*256+msg->Buffer[i+1];
188 		smprintf(s,"ParentID is %i\n",Priv->ParentID);
189 
190 		File->Type = GSM_File_Other;
191 		if (msg->Length > 240){
192 			i = 227;
193 			if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x01)
194 				File->Type = GSM_File_Image_JPG;
195 			else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x02)
196 				File->Type = GSM_File_Image_BMP;
197 			else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x07)
198 				File->Type = GSM_File_Image_BMP;
199 			else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x03)
200 				File->Type = GSM_File_Image_PNG;
201 			else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x05)
202 				File->Type = GSM_File_Image_GIF;
203 			else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x09)
204 				File->Type = GSM_File_Image_WBMP;
205 			else if (msg->Buffer[i]==0x04 && msg->Buffer[i+2]==0x01)
206 				File->Type = GSM_File_Sound_AMR;
207 			else if (msg->Buffer[i]==0x04 && msg->Buffer[i+2]==0x02)
208 				File->Type = GSM_File_Sound_MIDI;
209 			else if (msg->Buffer[i]==0x08 && msg->Buffer[i+2]==0x05)
210 				File->Type = GSM_File_Video_3GP;
211 			else if (msg->Buffer[i]==0x10 && msg->Buffer[i+2]==0x01)
212 				File->Type = GSM_File_Java_JAR;
213 			else if (msg->Buffer[i]==0x00 && msg->Buffer[i+2]==0x01)
214 				File->Type = GSM_File_MMS;
215 		}
216 		return ERR_NONE;
217 	case 0x2F:
218 		smprintf(s,"File or folder used bytes received\n");
219 		File->Used = msg->Buffer[6]*256*256*256+
220 			     msg->Buffer[7]*256*256+
221 			     msg->Buffer[8]*256+
222 			     msg->Buffer[9];
223 		return ERR_NONE;
224 	case 0x33:
225 		if (s->Phone.Data.RequestID == ID_GetFileInfo) {
226 
227 			newsize = msg->Buffer[8] * 256 + msg->Buffer[9];
228 
229 			error = N6510_AllocFileCache(s, Priv->FilesLocationsUsed + newsize);
230 			if (error != ERR_NONE) return error;
231 
232 			error = N6510_ShiftFileCache(s, newsize);
233 			if (error != ERR_NONE) return error;
234 
235 			for (i = 0; i < newsize; i++) {
236 				sprintf(buffer,"%i",msg->Buffer[13+i*4-1]*256 + msg->Buffer[13+i*4]);
237 				EncodeUnicode(Priv->FilesCache[i].ID_FullName,buffer,strlen(buffer));
238 				Priv->FilesCache[i].Level = File->Level+1;
239 				smprintf(s, "%s ",DecodeUnicodeString(Priv->FilesCache[i].ID_FullName));
240 			}
241 			smprintf(s, "\n");
242 		}
243 		if ((msg->Buffer[8]*256+msg->Buffer[9]) != 0x00) File->Folder = TRUE;
244 		return ERR_NONE;
245 	case 0xf0:
246 		smprintf(s, "File system is not supported\n");
247 		return ERR_NOTSUPPORTED;
248 	}
249 	return ERR_UNKNOWNRESPONSE;
250 }
251 
N6510_GetFileFolderInfo1(GSM_StateMachine * s,GSM_File * File,gboolean full)252 static GSM_Error N6510_GetFileFolderInfo1(GSM_StateMachine *s, GSM_File *File, gboolean full)
253 {
254 	GSM_Error	       	error;
255 	unsigned char	   	req[10] = {
256 		N7110_FRAME_HEADER,
257 		0x14,	   	/* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
258 		0x01,	   	/* 0x00 for sublocations reverse sorting, 0x01 for free */
259 		0x00, 0x00, 0x01,
260 		0x00, 0x01};    /* Folder or file number */
261 
262 	s->Phone.Data.FileInfo  = File;
263 	req[8]		  	= atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
264 	req[9]		  	= atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
265 
266 	req[3] = 0x14;
267 	req[4] = 0x01;
268 	smprintf(s,"Getting info for file in filesystem\n");
269 	error=GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
270 	if (error != ERR_NONE) return error;
271 
272 	if (full) {
273 		req[3] = 0x32;
274 		req[4] = 0x00;
275 		smprintf(s,"Getting subfolders for filesystem\n");
276 		error=GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
277 		if (error != ERR_NONE) return error;
278 	}
279 
280 	if (!File->Folder) {
281 		req[3] = 0x2E;
282 		req[4] = 0x01;
283 		smprintf(s,"Getting used memory for file in filesystem\n");
284 		return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
285 	}
286 
287 	return error;
288 }
289 
N6510_GetNextFileFolder1(GSM_StateMachine * s,GSM_File * File,gboolean start)290 static GSM_Error N6510_GetNextFileFolder1(GSM_StateMachine *s, GSM_File *File, gboolean start)
291 {
292 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
293 	GSM_Error	       	error;
294 	unsigned char		buffer[5];
295 
296 	if (start) {
297 		error = N6510_AllocFileCache(s, 1);
298 		if (error != ERR_NONE) return error;
299 
300 		Priv->FilesLocationsUsed = 1;
301 
302 		sprintf(buffer,"%i",0x01);
303 		EncodeUnicode(Priv->FilesCache[0].ID_FullName,buffer,strlen(buffer));
304 		Priv->FilesCache[0].Level = 1;
305 	}
306 
307 	while (1) {
308 		if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
309 
310 		CopyUnicodeString(File->ID_FullName,Priv->FilesCache[0].ID_FullName);
311 		File->Level = Priv->FilesCache[0].Level;
312 
313 		error = N6510_ShiftFileCache(s, -1);
314 		if (error != ERR_NONE) return error;
315 
316 		error = N6510_GetFileFolderInfo1(s, File, TRUE);
317 		if (error == ERR_EMPTY) continue;
318 		return error;
319 	}
320 }
321 
N6510_ReplyGetFileSystemStatus1(GSM_Protocol_Message * msg,GSM_StateMachine * s)322 GSM_Error N6510_ReplyGetFileSystemStatus1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
323 {
324 	switch (msg->Buffer[3]) {
325 	case 0x23:
326 		if (!strcmp(s->Phone.Data.ModelInfo->model,"6310i")) {
327 			smprintf(s,"File or folder total bytes received\n");
328 			s->Phone.Data.FileSystemStatus->Free =
329 				3*256*256 + msg->Buffer[8]*256 + msg->Buffer[9] -
330 				s->Phone.Data.FileSystemStatus->Used;
331 		} else {
332 			smprintf(s,"File or folder free bytes received\n");
333 			s->Phone.Data.FileSystemStatus->Free =
334 					msg->Buffer[6]*256*256*256+
335 					msg->Buffer[7]*256*256+
336 					msg->Buffer[8]*256+
337 					msg->Buffer[9];
338 		}
339 		return ERR_NONE;
340 	case 0x2F:
341 		smprintf(s,"File or folder used bytes received\n");
342 		s->Phone.Data.FileSystemStatus->Used =
343 				msg->Buffer[6]*256*256*256+
344 				msg->Buffer[7]*256*256+
345 				msg->Buffer[8]*256+
346 				msg->Buffer[9];
347 		return ERR_NONE;
348 	}
349 	return ERR_UNKNOWNRESPONSE;
350 }
351 
N6510_GetFileSystemStatus1(GSM_StateMachine * s,GSM_FileSystemStatus * status)352 static GSM_Error N6510_GetFileSystemStatus1(GSM_StateMachine *s, GSM_FileSystemStatus *status)
353 {
354 	GSM_Error	       	error;
355 	unsigned char	   	req[10] = {
356 		N7110_FRAME_HEADER,
357 		0x22,	   	/* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
358 		0x01,	   	/* 0x00 for sublocations reverse sorting, 0x01 for free */
359 		0x00, 0x00, 0x01,
360 		0x00, 0x01};    /* Folder or file number */
361 
362 	/* Used memory by types */
363 	status->UsedImages = 0;
364 	status->UsedSounds = 0;
365 	status->UsedThemes = 0;
366 	s->Phone.Data.FileSystemStatus = status;
367 
368 	status->Free = 0;
369 
370 	req[3] = 0x2E;
371 	req[4] = 0x01;
372 	smprintf(s, "Getting used/total memory in filesystem\n");
373 	error = GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
374 	if (error != ERR_NONE) return error;
375 
376 	req[3] = 0x22;
377 	req[4] = 0x01;
378 	smprintf(s, "Getting free memory in filesystem\n");
379 	return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
380 }
381 
N6510_GetFilePart1(GSM_StateMachine * s,GSM_File * File,int * Handle UNUSED,size_t * Size)382 static GSM_Error N6510_GetFilePart1(GSM_StateMachine *s, GSM_File *File, int *Handle UNUSED, size_t *Size)
383 {
384 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
385 	int		     	old;
386 	GSM_Error	       	error;
387 	unsigned char	   	req[] = {
388 		N7110_FRAME_HEADER, 0x0E, 0x00, 0x00, 0x00, 0x01,
389 		0x00, 0x01,	     	/* Folder or file number */
390 		0x00, 0x00, 0x00, 0x00, /* Start from xxx byte */
391 		0x00, 0x00,
392 		0x03, 0xE8};	    	/* Read xxx bytes */
393 
394 	if (File->Used == 0x00) {
395 		error = N6510_GetFileFolderInfo1(s, File, FALSE);
396 		if (error != ERR_NONE) return error;
397 
398 		if (File->Folder) return ERR_SHOULDBEFILE;
399 
400 		(*Size) 	= File->Used;
401 		File->Used 	= 0;
402 	}
403 
404 	old		 = File->Used;
405 	req[8]		 = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
406 	req[9]		 = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
407 	req[10]		 = old / (256*256*256);
408 	req[11]		 = old / (256*256);
409 	req[12]		 = old / 256;
410 	req[13]		 = old % 256;
411 
412 	s->Phone.Data.File = File;
413 	smprintf(s, "Getting file part from filesystem\n");
414 	error=GSM_WaitFor (s, req, 18, 0x6D, 4, ID_GetFile);
415 	if (error != ERR_NONE) return error;
416 	if (File->Used - old != (0x03 * 256 + 0xE8)) {
417 		error = N6510_GetFileCRC1(s, File->ID_FullName);
418 		if (error != ERR_NONE) return error;
419 
420 		if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
421 			smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
422 			return ERR_WRONGCRC;
423 		}
424 		return ERR_EMPTY;
425 	}
426 	return ERR_NONE;
427 }
428 
N6510_SetReadOnly1(GSM_StateMachine * s,unsigned char * ID,gboolean enable)429 static GSM_Error N6510_SetReadOnly1(GSM_StateMachine *s, unsigned char *ID, gboolean enable)
430 {
431 	unsigned char SetAttr[] = {
432 		N7110_FRAME_HEADER, 0x18,
433 		0x00, 		    /* state */
434 		0x00, 0x00, 0x01,
435 		0x00, 0x20};	    /* File ID */
436 
437 	if (!enable) SetAttr[4] = 0x06;
438 
439 	SetAttr[8] = atoi(DecodeUnicodeString(ID)) / 256;
440 	SetAttr[9] = atoi(DecodeUnicodeString(ID)) % 256;
441 	smprintf(s, "Setting readonly attribute\n");
442 	return GSM_WaitFor (s, SetAttr, 10, 0x6D, 4, ID_SetAttrib);
443 }
444 
N6510_SetFileAttributes1(GSM_StateMachine * s,GSM_File * File)445 static GSM_Error N6510_SetFileAttributes1(GSM_StateMachine *s, GSM_File *File)
446 {
447 	GSM_Error error;
448 	GSM_File  file2;
449 
450 	memset(&file2, 0, sizeof(file2));
451 
452 	CopyUnicodeString(file2.ID_FullName,File->ID_FullName);
453 	error = N6510_GetFileFolderInfo1(s, &file2, FALSE);
454 	if (error != ERR_NONE) return error;
455 
456 	/*  setting folder attrib works, but we block it */
457 	if (file2.Folder) return ERR_SHOULDBEFILE;
458 
459 	/*  todo */
460 	if (file2.System != File->System ||
461 	    file2.Hidden != File->Hidden ||
462 	    file2.Protected != File->Protected) {
463 		return ERR_NOTSUPPORTED;
464 	}
465 
466 	return N6510_SetReadOnly1(s, File->ID_FullName, File->ReadOnly);
467 }
468 
469 /* function checks if there is file/folder with searched name in folder with specified ID */
N6510_SearchForFileName1(GSM_StateMachine * s,GSM_File * File)470 static GSM_Error N6510_SearchForFileName1(GSM_StateMachine *s, GSM_File *File)
471 {
472 	GSM_Error	       	error;
473 	GSM_File		*BackupCache, *NewFiles;
474 	int		     	FilesLocationsUsed,FilesLocationsUsed2,i;
475 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
476 
477 	File->Folder = FALSE;
478 
479 	/* making backup */
480 	BackupCache = (GSM_File *)malloc(sizeof(GSM_File) * Priv->FilesLocationsUsed);
481 	if (BackupCache == NULL) return ERR_MOREMEMORY;
482 	memcpy(BackupCache, Priv->FilesCache, sizeof(GSM_File) * Priv->FilesLocationsUsed);
483 	FilesLocationsUsed = Priv->FilesLocationsUsed;
484 
485 	/* Allocate new cache */
486 	error = N6510_AllocFileCache(s, 1);
487 	if (error != ERR_NONE) {
488 		free(BackupCache);
489 		return error;
490 	}
491 
492 	/* putting own data */
493 	Priv->FilesCache[0].Level    	= 1;
494 	Priv->FilesLocationsUsed 	= 1;
495 	CopyUnicodeString(Priv->FilesCache[0].ID_FullName,File->ID_FullName);
496 
497 	/* checking */
498 	error = N6510_GetFileFolderInfo1(s, &Priv->FilesCache[0], TRUE);
499 
500 	/* backuping new data */
501 	NewFiles = (GSM_File *)malloc(sizeof(GSM_File) * Priv->FilesLocationsUsed);
502 	if (NewFiles == NULL) {
503 		free(BackupCache);
504 		BackupCache=NULL;
505 		return ERR_MOREMEMORY;
506 	}
507 	memcpy(NewFiles, Priv->FilesCache, sizeof(GSM_File) * Priv->FilesLocationsUsed);
508 	FilesLocationsUsed2 = Priv->FilesLocationsUsed;
509 
510 	/* restoring */
511 	memcpy(Priv->FilesCache, BackupCache, sizeof(GSM_File) * FilesLocationsUsed);
512 	free(BackupCache);
513 	BackupCache=NULL;
514 	Priv->FilesLocationsUsed = FilesLocationsUsed;
515 
516 	if (error != ERR_NONE) {
517 		free(NewFiles);
518 		NewFiles=NULL;
519 		return error;
520 	}
521 
522 	for (i = 0; i < FilesLocationsUsed2; i++) {
523 		smprintf(s, "ID is %s\n",DecodeUnicodeString(NewFiles[i].ID_FullName));
524 		error = N6510_GetFileFolderInfo1(s, &NewFiles[i], FALSE);
525 		if (error == ERR_EMPTY) continue;
526 		if (error != ERR_NONE) {
527 			free(NewFiles);
528 			NewFiles=NULL;
529 			return error;
530 		}
531 		smprintf(s, "%s",DecodeUnicodeString(File->Name));
532 		smprintf(s, "%s \n",DecodeUnicodeString(NewFiles[i].Name));
533 		if (mywstrncasecmp(NewFiles[i].Name,File->Name,0)) {
534 			smprintf(s, "the same\n");
535 			File->Folder = NewFiles[i].Folder;
536 			free(NewFiles);
537 			NewFiles=NULL;
538 			return ERR_NONE;
539 		}
540 	}
541 	free(NewFiles);
542 	NewFiles=NULL;
543 	return ERR_EMPTY;
544 }
545 
N6510_ReplyAddFileHeader1(GSM_Protocol_Message * msg,GSM_StateMachine * s)546 GSM_Error N6510_ReplyAddFileHeader1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
547 {
548 	unsigned char buffer[8];
549 
550 	switch (msg->Buffer[3]) {
551 	case 0x03:
552 		smprintf(s,"File header added\n");
553 		sprintf(buffer,"%i",msg->Buffer[8]*256+msg->Buffer[9]);
554 		EncodeUnicode(s->Phone.Data.File->ID_FullName,buffer,strlen(buffer));
555 		return ERR_NONE;
556 	case 0x13:
557 		return ERR_NONE;
558 	}
559 	return ERR_UNKNOWNRESPONSE;
560 }
561 
N6510_ReplyAddFilePart1(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s UNUSED)562 GSM_Error N6510_ReplyAddFilePart1(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s UNUSED)
563 {
564 	return ERR_NONE;
565 }
566 
N6510_AddFilePart1(GSM_StateMachine * s,GSM_File * File,size_t * Pos,int * Handle UNUSED)567 static GSM_Error N6510_AddFilePart1(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle UNUSED)
568 {
569 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
570 	GSM_File		File2;
571 	GSM_Error	       	error;
572 	int		     	j;
573 	unsigned char	   	Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
574 		N7110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x01,
575 		0x00, 0x0C,	     /* parent folder ID */
576 		0x00, 0x00, 0x00, 0xE8};
577 	unsigned char	   	Add[15000] = {
578 		N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
579 		0x00, 0x04,	     /* file ID */
580 		0x00, 0x00,
581 		0x01, 0x28};	     /* length */
582 	unsigned char 		end[30] = {
583 		N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
584 		0x00, 0x04,	     /* file ID */
585 		0x00, 0x00, 0x00, 0x00};
586 
587 	memset(&File2, 0, sizeof(File2));
588 
589 	s->Phone.Data.File = File;
590 
591 	if (*Pos == 0) {
592 		error = N6510_SearchForFileName1(s,File);
593 		if (error == ERR_NONE) return ERR_FILEALREADYEXIST;
594 		if (error != ERR_EMPTY) return error;
595 
596 		Header[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
597 		Header[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
598 		memset(Header+14, 0x00, 300);
599 		CopyUnicodeString(Header+14,File->Name);
600 		Header[222] = File->Used / (256*256*256);
601 		Header[223] = File->Used / (256*256);
602 		Header[224] = File->Used / 256;
603 		Header[225] = File->Used % 256;
604 		switch(File->Type) {
605 			case GSM_File_Image_JPG    : Header[231]=0x02; Header[233]=0x01; break;
606 			case GSM_File_Image_BMP    : Header[231]=0x02; Header[233]=0x02; break;
607 			case GSM_File_Image_PNG    : Header[231]=0x02; Header[233]=0x03; break;
608 			case GSM_File_Image_GIF    : Header[231]=0x02; Header[233]=0x05; break;
609 			case GSM_File_Image_WBMP   : Header[231]=0x02; Header[233]=0x09; break;
610 			case GSM_File_Sound_AMR    : Header[231]=0x04; Header[233]=0x01; break;
611 			case GSM_File_Sound_MIDI   : Header[231]=0x04; Header[233]=0x05; break; /* Header[238]=0x01; */
612 			case GSM_File_Sound_NRT    : Header[231]=0x04; Header[233]=0x06; break;
613 			case GSM_File_Video_3GP    : Header[231]=0x08; Header[233]=0x05; break;
614 			case GSM_File_Java_JAR     : Header[231]=0x10; Header[233]=0x01; break;
615 			case GSM_File_MMS:
616 				Header[214]=0x07;
617 				Header[215]=0xd3;
618 				Header[216]=0x06;
619 				Header[217]=0x01;
620 				Header[218]=0x12;
621 				Header[219]=0x13;
622 				Header[220]=0x29;
623 				Header[233]=0x01;
624 				break;
625 			default		    : Header[231]=0x01; Header[233]=0x05;
626 		}
627 		Header[235] = 0x01;
628 		Header[236] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
629 		Header[237] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
630 		if (File->Protected) Header[238] = 0x01; /* Nokia forward lock */
631 		if (File->Hidden)    Header[241] = 0x01;
632 		if (File->System)    Header[242] = 0x01; /* fixme */
633 		smprintf(s, "Adding file header\n");
634 		error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
635 		if (error != ERR_NONE) return error;
636 	}
637 
638 	j = 1000;
639 	if (File->Used - *Pos < 1000) j = File->Used - *Pos;
640 	Add[ 8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
641 	Add[ 9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
642 	Add[12] = j / 256;
643 	Add[13] = j % 256;
644 	memcpy(Add+14,File->Buffer+(*Pos),j);
645 	smprintf(s, "Adding file part %ld %i\n", (long)*Pos,j);
646 	error=GSM_WaitFor (s, Add, 14+j, 0x6D, 4, ID_AddFile);
647 	if (error != ERR_NONE) return error;
648 	*Pos = *Pos + j;
649 
650 	if (j < 1000) {
651 		/* FIXME: This looks strange */
652 		end[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
653 		end[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
654 		smprintf(s, "Frame for ending adding file\n");
655 		error = GSM_WaitFor (s, end, 14, 0x6D, 4, ID_AddFile);
656 		if (error != ERR_NONE) return error;
657 
658 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName);
659 		error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
660 		if (error != ERR_NONE) return error;
661 
662 		if (!File->ModifiedEmpty) {
663 			Header[3]   = 0x12;
664 			Header[4]   = 0x01;
665 			Header[12]  = 0x00;
666 			Header[13]  = 0xE8;
667 			Header[8]   = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
668 			Header[9]   = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
669 			memset(Header+14, 0x00, 300);
670 			CopyUnicodeString(Header+14,File->Name);
671 			NOKIA_EncodeDateTime(s,Header+214,&File->Modified);
672 			/* When you save too big file for phone and it changes
673 			 * size (some part is cut by firmware), you HAVE to write
674 			 * here correct file size. In other case filesystem
675 			 * will be damaged
676 			 */
677 			Header[224] = File2.Used / 256;
678 			Header[225] = File2.Used % 256;
679 			Header[226] = Priv->FileToken / 256;
680 			Header[227] = Priv->FileToken % 256;
681 			switch(File->Type) {
682 				case GSM_File_Image_JPG    : Header[231]=0x02; Header[233]=0x01; break;
683 				case GSM_File_Image_BMP    : Header[231]=0x02; Header[233]=0x02; break;
684 				case GSM_File_Image_PNG    : Header[231]=0x02; Header[233]=0x03; break;
685 				case GSM_File_Image_GIF    : Header[231]=0x02; Header[233]=0x05; break;
686 				case GSM_File_Image_WBMP   : Header[231]=0x02; Header[233]=0x09; break;
687 				case GSM_File_Sound_AMR    : Header[231]=0x04; Header[233]=0x01; break;
688 				case GSM_File_Sound_MIDI   : Header[231]=0x04; Header[233]=0x05; break; /* Header[238]=0x01; */
689 				case GSM_File_Sound_NRT    : Header[231]=0x04; Header[233]=0x06; break;
690 				case GSM_File_Video_3GP    : Header[231]=0x08; Header[233]=0x05; break;
691 				case GSM_File_Java_JAR     : Header[231]=0x10; Header[233]=0x01; break;
692 				case GSM_File_MMS:
693 					Header[214]=0x07;
694 					Header[215]=0xd3;
695 					Header[216]=0x06;
696 					Header[217]=0x01;
697 					Header[218]=0x12;
698 					Header[219]=0x13;
699 					Header[220]=0x29;
700 					Header[233]=0x01;
701 					break;
702 				default		    : Header[231]=0x01; Header[233]=0x05;
703 			}
704 			Header[235] = 0x01;
705 			Header[236] = Priv->ParentID / 256;
706 			Header[237] = Priv->ParentID % 256;
707 			smprintf(s, "Adding file header\n");
708 			error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
709 			if (error != ERR_NONE) return error;
710 		}
711 
712 		/* Can't delete from phone menu */
713 		if (File->ReadOnly) {
714 			error = N6510_SetReadOnly1(s, File->ID_FullName, TRUE);
715 			if (error != ERR_NONE) return error;
716 		}
717 
718 		error = N6510_GetFileCRC1(s, File->ID_FullName);
719 		if (error != ERR_NONE) return error;
720 
721 		if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
722 			smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
723 			return ERR_WRONGCRC;
724 		}
725 
726 		return ERR_EMPTY;
727 	}
728 
729 	return ERR_NONE;
730 }
731 
N6510_ReplyDeleteFileFolder1(GSM_Protocol_Message * msg,GSM_StateMachine * s UNUSED)732 GSM_Error N6510_ReplyDeleteFileFolder1(GSM_Protocol_Message *msg, GSM_StateMachine *s UNUSED)
733 {
734 	if (msg->Buffer[4] == 0x01) {
735 		return ERR_NONE;
736 	} else if (msg->Buffer[4] == 0x04) {
737 		return ERR_FILENOTEXIST;
738 	}
739 	return ERR_UNKNOWNRESPONSE;
740 }
741 
N6510_PrivDeleteFileFolder1(GSM_StateMachine * s,unsigned char * ID,gboolean file)742 static GSM_Error N6510_PrivDeleteFileFolder1(GSM_StateMachine *s, unsigned char *ID, gboolean file)
743 {
744 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
745 	GSM_File		File;
746 	GSM_Error       error;
747 	unsigned char   Delete[40] = {
748 		N7110_FRAME_HEADER, 0x1E, 0x00, 0x00, 0x00, 0x01,
749 		0x00, 0x35};	    /* File ID */
750 
751 	memset(&File, 0, sizeof(File));
752 
753 	Priv->FilesLocationsUsed = 0;
754 	CopyUnicodeString(File.ID_FullName,ID);
755 	error = N6510_GetFileFolderInfo1(s, &File, TRUE);
756 	if (error != ERR_NONE) return error;
757 	if (file) {
758 		if (File.Folder) return ERR_SHOULDBEFILE;
759 	} else {
760 		if (!File.Folder) return ERR_SHOULDBEFOLDER;
761 		/* dont allow to delete non empty folder */
762 		if (Priv->FilesLocationsUsed != 0) return ERR_FOLDERNOTEMPTY;
763 	}
764 
765 	error = N6510_SetReadOnly1(s, ID, FALSE);
766 	if (error != ERR_NONE) return error;
767 
768 	/* FIXME: This looks wrong */
769 	Delete[8] = atoi(DecodeUnicodeString(ID)) / 256;
770 	Delete[9] = atoi(DecodeUnicodeString(ID)) % 256;
771 
772 	return GSM_WaitFor (s, Delete, 10, 0x6D, 4, ID_DeleteFile);
773 }
774 
N6510_DeleteFile1(GSM_StateMachine * s,unsigned char * ID)775 static GSM_Error N6510_DeleteFile1(GSM_StateMachine *s, unsigned char *ID)
776 {
777 	return N6510_PrivDeleteFileFolder1(s,ID,TRUE);
778 }
779 
N6510_DeleteFolder1(GSM_StateMachine * s,unsigned char * ID)780 static GSM_Error N6510_DeleteFolder1(GSM_StateMachine *s, unsigned char *ID)
781 {
782 	return N6510_PrivDeleteFileFolder1(s,ID,FALSE);
783 }
784 
N6510_ReplyAddFolder1(GSM_Protocol_Message * msg,GSM_StateMachine * s)785 GSM_Error N6510_ReplyAddFolder1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
786 {
787 	unsigned char buffer[8];
788 
789 	sprintf(buffer,"%i",msg->Buffer[8]*256+msg->Buffer[9]);
790 	EncodeUnicode(s->Phone.Data.File->ID_FullName,buffer,strlen(buffer));
791 	return ERR_NONE;
792 }
793 
N6510_AddFolder1(GSM_StateMachine * s,GSM_File * File)794 static GSM_Error N6510_AddFolder1(GSM_StateMachine *s, GSM_File *File)
795 {
796 	GSM_File	File2;
797 	GSM_Error       error;
798 	unsigned char   Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
799 		N7110_FRAME_HEADER, 0x04, 0x00, 0x00, 0x00, 0x01,
800 		0x00, 0x0C,	     /* parent folder ID */
801 		0x00, 0x00, 0x00, 0xE8};
802 
803 	memset(&File2, 0, sizeof(File2));
804 
805 	CopyUnicodeString(File2.ID_FullName,File->ID_FullName);
806 	error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
807 	if (error != ERR_NONE) return error;
808 	if (!File2.Folder) return ERR_SHOULDBEFOLDER;
809 
810 	Header[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
811 	Header[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
812 	memset(Header+14, 0x00, 300);
813 	CopyUnicodeString(Header+14,File->Name);
814 	Header[233] = 0x02;
815 	Header[235] = 0x01;
816 	Header[236] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
817 	Header[237] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
818 
819 	s->Phone.Data.File = File;
820 	smprintf(s, "Adding folder\n");
821 	error = GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFolder);
822 	if (error != ERR_NONE) return error;
823 
824 	if (!strcmp(DecodeUnicodeString(File->ID_FullName),"0")) return ERR_FILEALREADYEXIST;
825 
826 	/* Can't delete from phone menu */
827 	if (File->ReadOnly) {
828 		error = N6510_SetReadOnly1(s, File->ID_FullName, TRUE);
829 		if (error != ERR_NONE) return error;
830 	}
831 
832 	return error;
833 }
834 
N6510_GetFolderListing1(GSM_StateMachine * s,GSM_File * File,gboolean start)835 static GSM_Error N6510_GetFolderListing1(GSM_StateMachine *s, GSM_File *File, gboolean start)
836 {
837 	GSM_Error	       	error;
838 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
839 
840 	if (start) {
841 		Priv->FilesLocationsUsed = 0;
842 
843 		error = N6510_GetFileFolderInfo1(s, File, TRUE);
844 		if (error != ERR_NONE) return error;
845 
846 		if (!File->Folder) return ERR_SHOULDBEFOLDER;
847 	}
848 
849 	while (TRUE) {
850 		if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
851 
852 		memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
853 		error = N6510_GetFileFolderInfo1(s, File, FALSE);
854 		if (error != ERR_NONE) return error;
855 
856 		error = N6510_ShiftFileCache(s, -1);
857 		if (error != ERR_NONE) return error;
858 
859 		break;
860 	}
861 	return error;
862 }
863 
864 /* filesystem 2 */
865 
N6510_ReplyOpenFile2(GSM_Protocol_Message * msg,GSM_StateMachine * s)866 GSM_Error N6510_ReplyOpenFile2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
867 {
868 	if (msg->Buffer[4]==0) {
869 		smprintf(s,"File opened and handle received\n");
870 		s->Phone.Data.FileHandle = msg->Buffer[6]*256*256*256+
871 				       msg->Buffer[7]*256*256+
872 				       msg->Buffer[8]*256+
873 				       msg->Buffer[9];
874 		smprintf(s,"File handle: %i\n",
875 				msg->Buffer[6]*256*256*256+
876 				msg->Buffer[7]*256*256+
877 				msg->Buffer[8]*256+
878 				msg->Buffer[9]);
879 		return ERR_NONE;
880 	} else if (msg->Buffer[4] == 0x03) {
881 		smprintf(s,"You can't open already existing folder\n");
882 		return ERR_FILEALREADYEXIST;
883 	} else if (msg->Buffer[4] == 0x06) {
884 		smprintf(s,"File not exist\n");
885 		return ERR_FILENOTEXIST;
886 	}
887 	return ERR_UNKNOWNRESPONSE;
888 }
889 
N6510_OpenFile2(GSM_StateMachine * s,char * Name,int * Handle,gboolean Create)890 static GSM_Error N6510_OpenFile2(GSM_StateMachine *s, char *Name, int *Handle, gboolean Create)
891 {
892 	unsigned char	 req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] =
893 		{N6110_FRAME_HEADER, 0x72,
894 				     0x00,	  /*  mode 0 - open read only, 0x11 - read write create */
895 				     0x02,
896 				     0xFF, 0xFF}; /*  name length */
897 	int		 Pos = 8;
898 	GSM_Error	 error;
899 
900 	if (Create) req[4] = 0x11;
901 	req[6] = (UnicodeLength(Name)*2 + 2)/ 256 ;
902 	req[7] = (UnicodeLength(Name)*2 + 2)% 256 ;
903 	CopyUnicodeString(req+8,Name);
904 	if (req[9] == 'a' || req[9] == 'A') req[9] = 'b';
905 	if (req[9] == 'd' || req[9] == 'D') req[9] = 'a';
906 	Pos+=UnicodeLength(Name)*2;
907 	req[Pos++] = 0;
908 	req[Pos++] = 0;
909 
910 	smprintf(s, "Opening file\n");
911 	error = GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_OpenFile);
912 	if (error==ERR_NONE) (*Handle) = s->Phone.Data.FileHandle;
913 	return error;
914 }
915 
N6510_CloseFile2(GSM_StateMachine * s,int * Handle)916 static GSM_Error N6510_CloseFile2(GSM_StateMachine *s, int *Handle)
917 {
918 	unsigned char	 req[200] = {N6110_FRAME_HEADER, 0x74, 0x00, 0x00,
919 				     0x00, 0x00, 0x00, 0x00}; /* file handle */
920 
921 	req[6]		 = (*Handle) / (256*256*256);
922 	req[7]		 = (*Handle) / (256*256);
923 	req[8]		 = (*Handle) / 256;
924 	req[9]		 = (*Handle) % 256;
925 
926 	smprintf(s, "Closing file\n");
927 	return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_CloseFile);
928 }
929 
N6510_GetFileCRC2(GSM_StateMachine * s,int * Handle)930 static GSM_Error N6510_GetFileCRC2(GSM_StateMachine *s, int *Handle)
931 {
932 	unsigned char req2[15000] = {
933 		N7110_FRAME_HEADER, 0x66, 0x00, 0x00,
934 		0x00, 0x00, 0x00, 0x00}; 	/*  handle */
935 
936 	req2[6]	= (*Handle) / (256*256*256);
937 	req2[7]	= (*Handle) / (256*256);
938 	req2[8]	= (*Handle) / 256;
939 	req2[9]	= (*Handle) % 256;
940 	return GSM_WaitFor (s, req2, 10, 0x6D, 8, ID_GetCRC);
941 }
942 
N6510_ReplyGetFileFolderInfo2(GSM_Protocol_Message * msg,GSM_StateMachine * s)943 GSM_Error N6510_ReplyGetFileFolderInfo2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
944 {
945 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
946 	GSM_File		*FileInfo = s->Phone.Data.FileInfo;
947 	GSM_File		*File;
948 	GSM_Error error;
949 
950 	switch (msg->Buffer[3]) {
951 	case 0x69:
952 	case 0x6D:
953 		switch (msg->Buffer[4]) {
954 		case 0x0C:
955 			smprintf(s,"Probably no MMC card\n");
956 			Priv->filesystem2error  = ERR_MEMORY;
957 			Priv->FilesEnd 		= TRUE;
958 			return ERR_MEMORY;
959 		case 0x00:
960 		case 0x0D:
961 			switch (msg->Buffer[5]) {
962 			case 0x00:
963 				break;
964 			case 0x06:
965 				smprintf(s,"File not exist\n");
966 				return ERR_FILENOTEXIST;
967 			case 0x0C:
968 				smprintf(s,"Probably no MMC card\n");
969 				return ERR_MEMORY;
970 			default:
971 				smprintf(s,"unknown status code\n");
972 				return ERR_UNKNOWNRESPONSE;
973 			}
974 			smprintf(s,"File or folder details received\n");
975 
976 			if (msg->Buffer[3] == 0x69) {
977 				/* File/Folder without can not be handled */
978 				if (UnicodeLength(msg->Buffer+32) == 0) {
979 					smprintf(s, "Ignoring file without name!\n");
980 					return ERR_NONE;
981 				}
982 				error = N6510_AllocFileCache(s, Priv->FilesLocationsUsed + 1);
983 				if (error != ERR_NONE) {
984 					return error;
985 				}
986 
987 				error = N6510_ShiftFileCache(s, 1);
988 				if (error != ERR_NONE) return error;
989 
990 				File = &Priv->FilesCache[1];
991 
992 				File->Level = Priv->FilesCache[0].Level + 1;
993 
994 				CopyUnicodeString(File->Name,msg->Buffer+32);
995 				smprintf(s,"\"%s\"\n",DecodeUnicodeString(File->Name));
996 
997 				CopyUnicodeString(File->ID_FullName,FileInfo->ID_FullName);
998 				EncodeUnicode(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,"/",1);
999 				CopyUnicodeString(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,msg->Buffer+32);
1000 				smprintf(s,"\"%s\"\n",DecodeUnicodeString(File->ID_FullName));
1001 			} else {
1002 				File = FileInfo;
1003 			}
1004 
1005 			smprintf(s, "File type: 0x%02X\n", msg->Buffer[29]);
1006 			if ((msg->Buffer[29] & 0x10) == 0x10) {
1007 				File->Folder = TRUE;
1008 				smprintf(s,"Folder\n");
1009 			} else {
1010 				File->Folder = FALSE;
1011 				smprintf(s,"File\n");
1012 				File->Used = msg->Buffer[10]*256*256*256+
1013 					    msg->Buffer[11]*256*256+
1014 					    msg->Buffer[12]*256+
1015 					    msg->Buffer[13];
1016 				smprintf(s,"Size %ld bytes\n", (long)File->Used);
1017 			}
1018 			File->ReadOnly = FALSE;
1019 			if ((msg->Buffer[29] & 1) == 1) {
1020 				File->ReadOnly = TRUE;
1021 				smprintf(s,"Readonly\n");
1022 			}
1023 			File->Hidden = FALSE;
1024 			if ((msg->Buffer[29] & 2) == 2) {
1025 				File->Hidden = TRUE;
1026 				smprintf(s,"Hidden\n");
1027 			}
1028 			File->System = FALSE;
1029 			if ((msg->Buffer[29] & 4) == 4) {
1030 				File->System = TRUE;
1031 				smprintf(s,"System\n");
1032 			}
1033 			File->Protected = FALSE;
1034 			if ((msg->Buffer[29] & 0x40) == 0x40) {
1035 				File->Protected = TRUE;
1036 				smprintf(s,"Protected\n");
1037 			}
1038 
1039 			File->ModifiedEmpty = FALSE;
1040 			NOKIA_DecodeDateTime(s, msg->Buffer+14, &File->Modified, TRUE, FALSE);
1041 			if (File->Modified.Year == 0x00) File->ModifiedEmpty = TRUE;
1042 			if (File->Modified.Year == 0xffff) File->ModifiedEmpty = TRUE;
1043 
1044 			if (msg->Buffer[3] == 0x69 && msg->Buffer[4] == 0) Priv->FilesEnd = TRUE;
1045 
1046 			return ERR_NONE;
1047 		case 0x06:
1048 			smprintf(s,"File or folder details received - not available ?\n");
1049 			Priv->filesystem2error  = ERR_FILENOTEXIST;
1050 			Priv->FilesEnd 		= TRUE;
1051 			return ERR_FILENOTEXIST;
1052 		case 0x0E:
1053 			smprintf(s,"File or folder details received - empty\n");
1054 			Priv->FilesEnd = TRUE;
1055 			return ERR_NONE;
1056 		}
1057 	}
1058 	return ERR_UNKNOWNRESPONSE;
1059 }
1060 
N6510_GetFileFolderInfo2(GSM_StateMachine * s,GSM_File * File)1061 static GSM_Error N6510_GetFileFolderInfo2(GSM_StateMachine *s, GSM_File *File)
1062 {
1063 	int		     	Pos=6;
1064 	unsigned char	   	req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1065 		N7110_FRAME_HEADER,0x6C,
1066 		0xFF, 0xFF}; 			/*  name length */
1067 
1068 	s->Phone.Data.FileInfo  = File;
1069 
1070 	req[4] = (UnicodeLength(File->ID_FullName)*2 + 2)/256;
1071 	req[5] = (UnicodeLength(File->ID_FullName)*2 + 2)%256;
1072 	CopyUnicodeString(req+6,File->ID_FullName);
1073 	if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1074 	if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1075 	Pos+=UnicodeLength(File->ID_FullName)*2;
1076 	req[Pos++] = 0;
1077 	req[Pos++] = 0;
1078 
1079 	smprintf(s,"Getting info for file in filesystem\n");
1080 	return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_GetFileInfo);
1081 }
1082 
N6510_PrivGetFolderListing2(GSM_StateMachine * s,GSM_File * File)1083 static GSM_Error N6510_PrivGetFolderListing2(GSM_StateMachine *s, GSM_File *File)
1084 {
1085 	GSM_Error		error;
1086 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1087 	unsigned char	   	req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1088 		N6110_FRAME_HEADER, 0x68,
1089 					    0xFF, 0xFF}; /*  name length */
1090 	int			Pos = 6, i = 0;
1091 
1092 	req[4] = (UnicodeLength(File->ID_FullName)*2 + 6)/ 256 ;
1093 	req[5] = (UnicodeLength(File->ID_FullName)*2 + 6)% 256 ;
1094 	CopyUnicodeString(req+6,File->ID_FullName);
1095 	if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1096 	if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1097 	Pos+=UnicodeLength(File->ID_FullName)*2;
1098 	req[Pos++] = 0;
1099 	req[Pos++] = '/';
1100 	req[Pos++] = 0;
1101 	req[Pos++] = '*';
1102 	req[Pos++] = 0;
1103 	req[Pos++] = 0;
1104 
1105 	smprintf(s, "Getting folder info %s\n",DecodeUnicodeString(File->ID_FullName));
1106 
1107 	Priv->filesystem2error  = ERR_NONE;
1108 	s->Phone.Data.FileInfo  = File;
1109 	Priv->FilesEnd 		= FALSE;
1110 	error = s->Protocol.Functions->WriteMessage(s, req, Pos, 0x6D);
1111 	if (error!=ERR_NONE) return error;
1112 
1113 	while (!Priv->FilesEnd) {
1114 		usleep(1000);
1115 		if (GSM_ReadDevice(s,TRUE) <= 0) {
1116 			i++;
1117 		} else {
1118 			i=0;
1119 		}
1120 		if (i == 3) {
1121 			smprintf(s,"Connection broken or WELL KNOWN phone firmware problem (which makes, that not all files are reported)\n");
1122 			Priv->filesystem2error  = ERR_FOLDERPART;
1123 			return ERR_NONE;
1124 		}
1125 	}
1126 
1127 	return ERR_NONE;
1128 }
1129 
N6510_GetNextFileFolder2(GSM_StateMachine * s,GSM_File * File,gboolean start)1130 static GSM_Error N6510_GetNextFileFolder2(GSM_StateMachine *s, GSM_File *File, gboolean start)
1131 {
1132 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1133 	GSM_Error	       	error;
1134 
1135 	if (start) {
1136 		error = N6510_AllocFileCache(s, 2);
1137 		if (error != ERR_NONE) return error;
1138 
1139 		Priv->FilesLocationsUsed = 2;
1140 
1141 		Priv->FilesCache[0].Level	= 1;
1142 		Priv->FilesCache[0].Folder	= TRUE;
1143 		Priv->FilesCache[0].Level	= 1;
1144 		Priv->FilesCache[0].ReadOnly = FALSE;
1145 		Priv->FilesCache[0].System = FALSE;
1146 		Priv->FilesCache[0].Hidden = FALSE;
1147 		Priv->FilesCache[0].Protected = FALSE;
1148 		EncodeUnicode(Priv->FilesCache[0].ID_FullName,"d:",2);
1149 		EncodeUnicode(Priv->FilesCache[0].Name,"D (Permanent_memory 2)",22);
1150 
1151 		Priv->FilesCache[1].Level	= 1;
1152 		Priv->FilesCache[1].Folder	= TRUE;
1153 		Priv->FilesCache[1].Level	= 1;
1154 		Priv->FilesCache[1].ReadOnly = FALSE;
1155 		Priv->FilesCache[1].System = FALSE;
1156 		Priv->FilesCache[1].Hidden = FALSE;
1157 		Priv->FilesCache[1].Protected = FALSE;
1158 		EncodeUnicode(Priv->FilesCache[1].ID_FullName,"a:",2);
1159 		EncodeUnicode(Priv->FilesCache[1].Name,"A (Memory card)",15);
1160 	}
1161 
1162 	smprintf(s, "Currently %i locations\n",Priv->FilesLocationsUsed);
1163 	if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
1164 
1165 
1166 	if (!Priv->FilesCache[0].Folder) {
1167 		memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1168 		error = N6510_ShiftFileCache(s, -1);
1169 		if (error != ERR_NONE) return error;
1170 		smprintf(s, "Returning file %s, level %d\n", DecodeUnicodeString(File->ID_FullName), File->Level);
1171 		return ERR_NONE;
1172 	}
1173 
1174 	memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1175 	error = N6510_PrivGetFolderListing2(s, File);
1176 	if (error != ERR_NONE) return error;
1177 
1178 	memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1179 	error = N6510_ShiftFileCache(s, -1);
1180 	if (error != ERR_NONE) return error;
1181 
1182 	smprintf(s, "Returning folder %s, level %d\n", DecodeUnicodeString(File->ID_FullName), File->Level);
1183 
1184 	if (Priv->filesystem2error == ERR_FOLDERPART) return ERR_FOLDERPART;
1185 
1186 	return error;
1187 }
1188 
N6510_GetFilePart2(GSM_StateMachine * s,GSM_File * File,int * Handle,size_t * Size)1189 static GSM_Error N6510_GetFilePart2(GSM_StateMachine *s, GSM_File *File, int *Handle, size_t *Size)
1190 {
1191 	int		    	old,j;
1192 	GSM_Error	       	error;
1193 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1194 	unsigned char	   	req[] = {
1195 		N7110_FRAME_HEADER, 0x5E, 0x00, 0x00,
1196 		0x00, 0x00, 0x00, 0x01,		/* file handle */
1197 		0x00, 0x00, 0x00, 0x00, 	/* position */
1198 		0x00, 0x00, 0x03, 0xE8, 	/* length */
1199 		0x00, 0x00, 0x03, 0xE8};	/* buffer length */
1200 
1201 	if (File->Used == 0x00) {
1202 		error = N6510_GetFileFolderInfo2(s, File);
1203 		if (error != ERR_NONE) return error;
1204 
1205 		if (File->Folder) return ERR_SHOULDBEFILE;
1206 
1207 		error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE);
1208 		if (error != ERR_NONE) return error;
1209 
1210 		for (j=UnicodeLength(File->ID_FullName)-1;j>0;j--) {
1211 			if (File->ID_FullName[j*2+1] == '\\' || File->ID_FullName[j*2+1] == '/') break;
1212 		}
1213 		if (File->ID_FullName[j*2+1] == '\\' || File->ID_FullName[j*2+1] == '/') {
1214 			CopyUnicodeString(File->Name,File->ID_FullName+j*2+2);
1215 		} else {
1216 			CopyUnicodeString(File->Name,File->ID_FullName);
1217 		}
1218 
1219 		(*Size) 	= File->Used;
1220 		File->Used 	= 0;
1221 	}
1222 
1223 	req[6]		 = (*Handle) / (256*256*256);
1224 	req[7]		 = (*Handle) / (256*256);
1225 	req[8]		 = (*Handle) / 256;
1226 	req[9]		 = (*Handle) % 256;
1227 
1228 	old		 = File->Used;
1229 	req[10]		 = old / (256*256*256);
1230 	req[11]		 = old / (256*256);
1231 	req[12]		 = old / 256;
1232 	req[13]		 = old % 256;
1233 
1234 	s->Phone.Data.File      = File;
1235 	smprintf(s, "Getting file part from filesystem\n");
1236 	error=GSM_WaitFor (s, req, 22, 0x6D, 4, ID_GetFile);
1237 	if (error != ERR_NONE) return error;
1238 
1239 	if (File->Used - old != (0x03 * 256 + 0xE8)) {
1240 		error = N6510_GetFileCRC2(s, Handle);
1241 		if (error != ERR_NONE) return error;
1242 
1243 		error = N6510_CloseFile2(s, Handle);
1244 		if (error != ERR_NONE) return error;
1245 
1246 		if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
1247 			smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
1248 			return ERR_WRONGCRC;
1249 		}
1250 
1251 		return ERR_EMPTY;
1252 	}
1253 	return ERR_NONE;
1254 }
1255 
N6510_ReplySetFileDate2(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s UNUSED)1256 GSM_Error N6510_ReplySetFileDate2(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s UNUSED)
1257 {
1258 	return ERR_NONE;
1259 }
1260 
N6510_ReplySetAttrib2(GSM_Protocol_Message * msg,GSM_StateMachine * s UNUSED)1261 GSM_Error N6510_ReplySetAttrib2(GSM_Protocol_Message *msg, GSM_StateMachine *s UNUSED)
1262 {
1263 	if (msg->Buffer[4] == 0x00) {
1264 		return ERR_NONE;
1265 	} else if (msg->Buffer[4] == 0x06) {
1266 		return ERR_FILENOTEXIST;
1267 	}
1268 	return ERR_UNKNOWNRESPONSE;
1269 }
1270 
N6510_SetFileAttributes2(GSM_StateMachine * s,GSM_File * File)1271 static GSM_Error N6510_SetFileAttributes2(GSM_StateMachine *s, GSM_File *File)
1272 {
1273 	int		P = 10;
1274 	GSM_Error	error;
1275 	GSM_File	File2;
1276 	unsigned char	Header2[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1277 		N7110_FRAME_HEADER, 0x6E,
1278 		0x00, 0x0c};			/* name len */
1279 
1280 	memcpy(&File2,File,sizeof(GSM_File));
1281 
1282 	error = N6510_GetFileFolderInfo2(s, File);
1283 	if (error != ERR_NONE) return error;
1284 
1285 	/* haven't checked. */
1286 	if (File->Folder) return ERR_SHOULDBEFILE;
1287 
1288 	Header2[4] = (UnicodeLength(File2.ID_FullName) + 1)/ 256 ;
1289 	Header2[5] = (UnicodeLength(File2.ID_FullName) + 1)% 256 ;
1290 	Header2[6] = 0x00;
1291 	Header2[7] = 0x00;
1292 	Header2[8] = 0x00;
1293 	Header2[9] = 0x00;
1294 	if (File2.ReadOnly)  Header2[9] += 1;
1295 	if (File2.Hidden)    Header2[9] += 2;
1296 	if (File2.System)    Header2[9] += 4;
1297 	if (File2.Protected) Header2[9] += 0x40;
1298 	CopyUnicodeString(Header2+10,File2.ID_FullName);
1299 	if (Header2[11] == 'a' || Header2[11] == 'A') Header2[11] = 'b';
1300 	if (Header2[11] == 'd' || Header2[11] == 'D') Header2[11] = 'a';
1301 	P+=UnicodeLength(File2.ID_FullName)*2;
1302 	Header2[P++] = 0;
1303 	Header2[P++] = 0;
1304 	error = GSM_WaitFor (s, Header2, P, 0x6D, 4, ID_SetAttrib);
1305 	if (error != ERR_NONE) return error;
1306 
1307 	error = N6510_GetFileFolderInfo2(s, File);
1308 	if (error != ERR_NONE) return error;
1309 
1310 	/* mmc doesn't support protected */
1311 	if (File2.System    != File->System     ||
1312 	    File2.ReadOnly  != File->ReadOnly   ||
1313 	    File2.Hidden    != File->Hidden     ) {
1314 /* 	    File2.Protected != File->Protected) { */
1315 		return ERR_NOTSUPPORTED;
1316 	}
1317 
1318 	return ERR_NONE;
1319 }
1320 
N6510_AddFilePart2(GSM_StateMachine * s,GSM_File * File,size_t * Pos,int * Handle)1321 static GSM_Error N6510_AddFilePart2(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle)
1322 {
1323 	GSM_Error	       	error;
1324 	int		     	j,P;
1325 /* 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510; */
1326 /* 	unsigned char		buffer[500]; */
1327 	unsigned char	   	req[15000] = {
1328 		N7110_FRAME_HEADER, 0x58, 0x00, 0x00,
1329 		0x00, 0x00, 0x00, 0x00, 	/*  handle */
1330 		0x00, 0x00, 0x04, 0x00};	/*  buffer len */
1331 	unsigned char	   	Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1332 		N7110_FRAME_HEADER, 0x86,
1333 		0x00, 0x0c};			/* name len */
1334 
1335 	s->Phone.Data.File = File;
1336 
1337 	if (*Pos == 0) {
1338 		EncodeUnicode(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,"/",1);
1339 		CopyUnicodeString(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,File->Name);
1340 
1341 		error = N6510_GetFileFolderInfo2(s, File);
1342 		switch (error) {
1343 		case ERR_FILENOTEXIST:
1344 			break;
1345 		case ERR_NONE:
1346 			return ERR_FILEALREADYEXIST;
1347 		default:
1348 			return error;
1349 		}
1350 
1351 		error = N6510_OpenFile2(s, File->ID_FullName, Handle, TRUE);
1352 		if (error != ERR_NONE) return error;
1353 	}
1354 
1355 	req[6]		 = (*Handle) / (256*256*256);
1356 	req[7]		 = (*Handle) / (256*256);
1357 	req[8]		 = (*Handle) / 256;
1358 	req[9]		 = (*Handle) % 256;
1359 
1360 	j = 2000;
1361 	if (File->Used - *Pos < 2000) j = File->Used - *Pos;
1362 	req[10]		 = j / (256*256*256);
1363 	req[11]		 = j / (256*256);
1364 	req[12]		 = j / 256;
1365 	req[13]		 = j % 256;
1366 	memcpy(req+14,File->Buffer+(*Pos),j);
1367 
1368 	smprintf(s, "Adding file part %ld %i\n",(long)*Pos,j);
1369 	error=GSM_WaitFor (s, req, 14+j, 0x6D, 4, ID_AddFile);
1370 	if (error != ERR_NONE) return error;
1371 	*Pos = *Pos + j;
1372 
1373 	if (j < 2000) {
1374 		error = N6510_CloseFile2(s, Handle);
1375 		if (error != ERR_NONE) return error;
1376 
1377 		P = 14;
1378 		Header[4] = (UnicodeLength(File->ID_FullName) + 1)/ 256 ;
1379 		Header[5] = (UnicodeLength(File->ID_FullName) + 1)% 256 ;
1380 		Header[6] = File->Modified.Year / 256;
1381 		Header[7] = File->Modified.Year % 256;
1382 		Header[8] = File->Modified.Month;
1383 		Header[9] = File->Modified.Day;
1384 		Header[10] = 0x00;
1385 		Header[11] = File->Modified.Hour;
1386 		Header[12] = File->Modified.Minute;
1387 		Header[13] = File->Modified.Second;
1388 		CopyUnicodeString(Header+14,File->ID_FullName);
1389 	 	if (Header[15] == 'a' || Header[15] == 'A') Header[15] = 'b';
1390 		if (Header[15] == 'd' || Header[15] == 'D') Header[15] = 'a';
1391 		P+=UnicodeLength(File->ID_FullName)*2;
1392 		req[P++] = 0;
1393 		req[P++] = 0;
1394 		smprintf(s,"Setting file date\n");
1395 		error = GSM_WaitFor (s, Header, P, 0x6D, 4, ID_AddFile);
1396 		if (error != ERR_NONE) return error;
1397 
1398 		error = N6510_SetFileAttributes2(s,File);
1399 		if (error != ERR_NONE) return error;
1400 
1401 /* 		error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE); */
1402 /* 		if (error != ERR_NONE) return error; */
1403 /* 		if ((*Handle) == 0) { */
1404 /* 			error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE); */
1405 /* 			if (error != ERR_NONE) return error; */
1406 /* 		} */
1407 /* 		error = N6510_GetFileCRC2(s, Handle); */
1408 /* 		if (error != ERR_NONE) return error; */
1409 /* 		error = N6510_CloseFile2(s, Handle); */
1410 /* 		if (error != ERR_NONE) return error; */
1411 /* 		if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) { */
1412 /* 			smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum); */
1413 /* 			return ERR_WRONGCRC; */
1414 /* 		} */
1415 
1416 		return ERR_EMPTY;
1417 	}
1418 
1419 	return ERR_NONE;
1420 }
1421 
N6510_GetFolderListing2(GSM_StateMachine * s,GSM_File * File,gboolean start)1422 static GSM_Error N6510_GetFolderListing2(GSM_StateMachine *s, GSM_File *File, gboolean start)
1423 {
1424 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1425 	GSM_Error 		error;
1426 
1427 	if (start) {
1428 		if (strcasecmp(DecodeUnicodeString(File->ID_FullName),"a:") == 0   ||
1429 		    strcasecmp(DecodeUnicodeString(File->ID_FullName),"a:\\") == 0 ||
1430 		    strcasecmp(DecodeUnicodeString(File->ID_FullName),"d:") == 0   ||
1431 		    strcasecmp(DecodeUnicodeString(File->ID_FullName),"d:\\") == 0) {
1432 		} else {
1433 			/* we must check, if user gave folder name or not */
1434 			error = N6510_GetFileFolderInfo2(s, File);
1435 			if (error != ERR_NONE) return error;
1436 			if (!File->Folder) return ERR_SHOULDBEFOLDER;
1437 		}
1438 
1439 		error = N6510_AllocFileCache(s, 1);
1440 		if (error != ERR_NONE) return error;
1441 
1442 		Priv->FilesLocationsUsed = 1;
1443 
1444 		error = N6510_PrivGetFolderListing2(s, File);
1445 		if (error != ERR_NONE) return error;
1446 
1447 		memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1448 
1449 		error = N6510_ShiftFileCache(s, -1);
1450 		if (error != ERR_NONE) return error;
1451 	}
1452 
1453 	if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
1454 
1455 	memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1456 
1457 	error = N6510_ShiftFileCache(s, -1);
1458 	if (error != ERR_NONE) return error;
1459 
1460 	if (start) {
1461 		if (Priv->filesystem2error == ERR_FOLDERPART) return ERR_FOLDERPART;
1462 	}
1463 	return ERR_NONE;
1464 }
1465 
N6510_ReplyDeleteFile2(GSM_Protocol_Message * msg,GSM_StateMachine * s UNUSED)1466 GSM_Error N6510_ReplyDeleteFile2(GSM_Protocol_Message *msg, GSM_StateMachine *s UNUSED)
1467 {
1468 	if (msg->Buffer[4] == 0x00) {
1469 		return ERR_NONE;
1470 	} else if (msg->Buffer[4] == 0x03) {
1471 		/* trying to delete read only */
1472 		return ERR_UNKNOWN;
1473 	} else if (msg->Buffer[4] == 0x06) {
1474 		return ERR_FILENOTEXIST;
1475 	}
1476 
1477 	return ERR_UNKNOWNRESPONSE;
1478 }
1479 
N6510_DeleteFile2(GSM_StateMachine * s,unsigned char * ID)1480 static GSM_Error N6510_DeleteFile2(GSM_StateMachine *s, unsigned char *ID)
1481 {
1482 	unsigned char   req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1483 		N7110_FRAME_HEADER, 0x62};
1484 	int		Pos = 6;
1485 	GSM_File	file;
1486 	GSM_Error	error;
1487 
1488 	/* first remove readonly */
1489 	file.ReadOnly  = FALSE;
1490 	file.Hidden    = FALSE;
1491 	file.System    = FALSE;
1492 	file.Protected = FALSE;
1493 
1494 	CopyUnicodeString(file.ID_FullName,ID);
1495 	error = N6510_SetFileAttributes2(s,&file);
1496 	if (error != ERR_NONE) return error;
1497 
1498 	req[4] = (UnicodeLength(ID)*2 + 2)/ 256 ;
1499 	req[5] = (UnicodeLength(ID)*2 + 2)% 256 ;
1500 	CopyUnicodeString(req+6,ID);
1501 	if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1502 	if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1503 	Pos+=UnicodeLength(ID)*2;
1504 	req[Pos++] = 0;
1505 	req[Pos++] = 0;
1506 
1507 	smprintf(s,"Deleting file\n");
1508 	return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_DeleteFile);
1509 }
1510 
N6510_ReplyAddFolder2(GSM_Protocol_Message * msg,GSM_StateMachine * s UNUSED)1511 GSM_Error N6510_ReplyAddFolder2(GSM_Protocol_Message *msg, GSM_StateMachine *s UNUSED)
1512 {
1513 	if (msg->Buffer[4] == 0x00) {
1514 		return ERR_NONE;
1515 	} if (msg->Buffer[4] == 0x04) {
1516 		return ERR_FILEALREADYEXIST;
1517 	} if (msg->Buffer[4] == 0x06) {
1518 		return ERR_FILENOTEXIST;
1519 	} if (msg->Buffer[4] == 0x0C) {
1520 		return ERR_MEMORY;
1521 	}
1522 	return ERR_UNKNOWNRESPONSE;
1523 }
1524 
N6510_AddFolder2(GSM_StateMachine * s,GSM_File * File)1525 static GSM_Error N6510_AddFolder2(GSM_StateMachine *s, GSM_File *File)
1526 {
1527 	GSM_Error	error;
1528 	unsigned char   req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1529 		N7110_FRAME_HEADER, 0x64};
1530 	int		Pos = 6;
1531 	int		Len = 0;
1532 
1533 	Len = UnicodeLength(File->ID_FullName)*2 + 2;
1534 
1535 	CopyUnicodeString(req+6,File->ID_FullName);
1536 	Pos+=UnicodeLength(File->ID_FullName)*2;
1537 	if (DecodeUnicodeString(File->ID_FullName)[UnicodeLength(File->ID_FullName)-1] != '\\' &&
1538 	    DecodeUnicodeString(File->ID_FullName)[UnicodeLength(File->ID_FullName)-1] != '/') {
1539 		req[Pos++] = 0;
1540 		req[Pos++] = '/';
1541 		Len += 2;
1542 	}
1543 	CopyUnicodeString(req+Pos,File->Name);
1544 	if (req[Pos+1] == 'a' || req[Pos+1] == 'A') req[Pos+1] = 'b';
1545 	if (req[Pos+1] == 'd' || req[Pos+1] == 'D') req[Pos+1] = 'a';
1546 	Pos += UnicodeLength(File->Name)*2;
1547 	Len += UnicodeLength(File->Name)*2;
1548 	req[Pos++] = 0;
1549 	req[Pos++] = 0;
1550 	req[4] = Len / 256 ;
1551 	req[5] = Len % 256 ;
1552 	smprintf(s,"Adding folder\n");
1553 	error=GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_AddFolder);
1554 	if (error == ERR_NONE) memcpy(File->ID_FullName,req+6,Pos);
1555 	return error;
1556 }
1557 
N6510_ReplyDeleteFolder2(GSM_Protocol_Message * msg,GSM_StateMachine * s UNUSED)1558 GSM_Error N6510_ReplyDeleteFolder2(GSM_Protocol_Message *msg, GSM_StateMachine *s UNUSED)
1559 {
1560 	if (msg->Buffer[4] == 0x00) {
1561 		return ERR_NONE;
1562 	} if (msg->Buffer[4] == 0x03) {
1563 		return ERR_SHOULDBEFOLDER;
1564 	} if (msg->Buffer[4] == 0x06) {
1565 		return ERR_FILENOTEXIST;
1566 	} if (msg->Buffer[4] == 0x0C) {
1567 		return ERR_MEMORY;
1568 	}
1569 	return ERR_UNKNOWNRESPONSE;
1570 }
1571 
N6510_DeleteFolder2(GSM_StateMachine * s,unsigned char * ID)1572 static GSM_Error N6510_DeleteFolder2(GSM_StateMachine *s, unsigned char *ID)
1573 {
1574 	GSM_File	File2;
1575 	GSM_Error	error;
1576 	unsigned char   req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1577 		N7110_FRAME_HEADER, 0x6A};
1578 	int		Pos = 6;
1579 
1580 	/* we don't want to allow deleting non empty folders */
1581 	CopyUnicodeString(File2.ID_FullName,ID);
1582 	error = N6510_GetFolderListing2(s, &File2, TRUE);
1583 	switch (error) {
1584 		case ERR_EMPTY:
1585 			break;
1586 		case ERR_NONE:
1587 			return ERR_FOLDERNOTEMPTY;
1588 		default:
1589 			return error;
1590 	}
1591 
1592 	req[4] = (UnicodeLength(ID)*2 + 2)/ 256 ;
1593 	req[5] = (UnicodeLength(ID)*2 + 2)% 256 ;
1594 	CopyUnicodeString(req+6,ID);
1595 	if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1596 	if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1597 	Pos+=UnicodeLength(ID)*2;
1598 	req[Pos++] = 0;
1599 	req[Pos++] = 0;
1600 
1601 	smprintf(s,"Deleting folder\n");
1602 	return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_DeleteFolder);
1603 }
1604 
1605 /* shared */
1606 
N6510_GetFolderListing(GSM_StateMachine * s,GSM_File * File,gboolean start)1607 GSM_Error N6510_GetFolderListing(GSM_StateMachine *s, GSM_File *File, gboolean start)
1608 {
1609 	GSM_Error	error;
1610 	GSM_File	File2;
1611 
1612 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1613 
1614 	if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1615 	    DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1616 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1617 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1618 			return ERR_NOTSUPPORTED;
1619 		}
1620 
1621 		memcpy(&File2,File,sizeof(GSM_File));
1622 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1623 		error = N6510_GetFolderListing1(s,&File2,start);
1624 		memcpy(File,&File2,sizeof(GSM_File));
1625 		/* GetFolderListing changes ID */
1626 		EncodeUnicode(File->ID_FullName,"c:/",3);
1627 		CopyUnicodeString(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,File2.ID_FullName);
1628 		return error;
1629 	} else {
1630 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1631 			return N6510_GetFolderListing2(s,File,start);
1632 		} else {
1633 			return ERR_NOTSUPPORTED;
1634 		}
1635 	}
1636 }
1637 
N6510_GetNextFileFolder(GSM_StateMachine * s,GSM_File * File,gboolean start)1638 GSM_Error N6510_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, gboolean start)
1639 {
1640 	GSM_Error	       	error;
1641 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1642 	char		    	buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1643 
1644 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1645 
1646 	if (start) {
1647 		Priv->UseFs1 = TRUE;
1648 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30)) {
1649 			/* series 40 3.0 don't have filesystem 1 */
1650 			Priv->UseFs1 = FALSE;
1651 		}
1652 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1653 			Priv->UseFs1 = FALSE;
1654 		}
1655 	}
1656 	if (Priv->UseFs1) {
1657 		error = N6510_GetNextFileFolder1(s,File,start);
1658 		if (error == ERR_EMPTY) {
1659 			if (!GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1660 				return error;
1661 			}
1662 			Priv->UseFs1      = FALSE;
1663 			start	   	= TRUE;
1664 		} else {
1665 			if (error == ERR_NONE) {
1666 				sprintf(buf,"c:/%s",DecodeUnicodeString(File->ID_FullName));
1667 				EncodeUnicode(File->ID_FullName,buf,strlen(buf));
1668 
1669 				if (File->Level != 1) return error;
1670 
1671 				buf[0] = 0;
1672 				buf[1] = 0;
1673 				CopyUnicodeString(buf,File->Name);
1674 				EncodeUnicode(File->Name,"C (",3);
1675 				CopyUnicodeString(File->Name+6,buf);
1676 				EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1677 			}
1678 			return error;
1679 		}
1680 	}
1681 	return N6510_GetNextFileFolder2(s,File,start);
1682 }
1683 
N6510_GetFilePart(GSM_StateMachine * s,GSM_File * File,int * Handle,size_t * Size)1684 GSM_Error N6510_GetFilePart(GSM_StateMachine *s, GSM_File *File, int *Handle, size_t *Size)
1685 {
1686 	GSM_File	File2;
1687 	char	    	buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1688 	GSM_Error       error;
1689 
1690 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1691 
1692 	if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1693 	    DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1694 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1695 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1696 			return ERR_NOTSUPPORTED;
1697 		}
1698 		memcpy(&File2,File,sizeof(GSM_File));
1699 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1700 		error = N6510_GetFilePart1(s,&File2, Handle, Size);
1701 		CopyUnicodeString(buf,File->ID_FullName);
1702 		memcpy(File,&File2,sizeof(GSM_File));
1703 		CopyUnicodeString(File->ID_FullName,buf);
1704 		return error;
1705 	} else {
1706 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1707 			return N6510_GetFilePart2(s,File, Handle, Size);
1708 		} else {
1709 			return ERR_NOTSUPPORTED;
1710 		}
1711 	}
1712 }
1713 
N6510_AddFilePart(GSM_StateMachine * s,GSM_File * File,size_t * Pos,int * Handle)1714 GSM_Error N6510_AddFilePart(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle)
1715 {
1716 	GSM_File	File2;
1717 	GSM_Error       error;
1718 
1719 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1720 
1721 	if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1722 	    DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1723 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1724 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1725 			return ERR_NOTSUPPORTED;
1726 		}
1727 
1728 		memcpy(&File2,File,sizeof(GSM_File));
1729 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1730 		error = N6510_AddFilePart1(s,&File2,Pos,Handle);
1731 		memcpy(File,&File2,sizeof(GSM_File));
1732 		/* addfilepart returns new ID */
1733 		EncodeUnicode(File->ID_FullName,"c:/",3);
1734 		CopyUnicodeString(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,File2.ID_FullName);
1735 		return error;
1736 	} else {
1737 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1738 			return N6510_AddFilePart2(s,File,Pos,Handle);
1739 		} else {
1740 			return ERR_NOTSUPPORTED;
1741 		}
1742 	}
1743 }
1744 
N6510_DeleteFile(GSM_StateMachine * s,unsigned char * ID)1745 GSM_Error N6510_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
1746 {
1747 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1748 
1749 	if (DecodeUnicodeString(ID)[0] == 'c' ||
1750 	    DecodeUnicodeString(ID)[0] == 'C') {
1751 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1752 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1753 			return ERR_NOTSUPPORTED;
1754 		}
1755 
1756 		return N6510_DeleteFile1(s,ID+6);
1757 	} else {
1758 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1759 			return N6510_DeleteFile2(s,ID);
1760 		} else {
1761 			return ERR_NOTSUPPORTED;
1762 		}
1763 	}
1764 }
1765 
N6510_AddFolder(GSM_StateMachine * s,GSM_File * File)1766 GSM_Error N6510_AddFolder(GSM_StateMachine *s, GSM_File *File)
1767 {
1768 	GSM_File	File2;
1769 	GSM_Error       error;
1770 
1771 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1772 
1773 	if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1774 	    DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1775 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1776 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1777 			return ERR_NOTSUPPORTED;
1778 		}
1779 		memcpy(&File2,File,sizeof(GSM_File));
1780 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1781 		error = N6510_AddFolder1(s,&File2);
1782 		memcpy(File,&File2,sizeof(GSM_File));
1783 		/* addfolder returns new ID */
1784 		EncodeUnicode(File->ID_FullName,"c:/",3);
1785 		CopyUnicodeString(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,File2.ID_FullName);
1786 		return error;
1787 	} else {
1788 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1789 			return N6510_AddFolder2(s,File);
1790 		} else {
1791 			return ERR_NOTSUPPORTED;
1792 		}
1793 	}
1794 }
1795 
N6510_DeleteFolder(GSM_StateMachine * s,unsigned char * ID)1796 GSM_Error N6510_DeleteFolder(GSM_StateMachine *s, unsigned char *ID)
1797 {
1798 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1799 
1800 	if (DecodeUnicodeString(ID)[0] == 'c' ||
1801 	    DecodeUnicodeString(ID)[0] == 'C') {
1802 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1803 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1804 			return ERR_NOTSUPPORTED;
1805 		}
1806 		return N6510_DeleteFolder1(s,ID+6);
1807 	} else {
1808 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1809 			return N6510_DeleteFolder2(s,ID);
1810 		} else {
1811 			return ERR_NOTSUPPORTED;
1812 		}
1813 	}
1814 }
1815 
N6510_GetFileSystemStatus(GSM_StateMachine * s,GSM_FileSystemStatus * status)1816 GSM_Error N6510_GetFileSystemStatus(GSM_StateMachine *s, GSM_FileSystemStatus *status)
1817 {
1818 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1819 
1820 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1821 		return ERR_NOTSUPPORTED;
1822 	} else {
1823 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1824 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1825 			return ERR_NOTSUPPORTED;
1826 		}
1827 		return N6510_GetFileSystemStatus1(s,status);
1828 	}
1829 }
1830 
N6510_SetFileAttributes(GSM_StateMachine * s,GSM_File * File)1831 GSM_Error N6510_SetFileAttributes(GSM_StateMachine *s, GSM_File *File)
1832 {
1833 	GSM_File	File2;
1834 	char	    	buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1835 	GSM_Error       error;
1836 
1837 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1838 
1839 	if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1840 	    DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1841 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1842 		    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1843 			return ERR_NOTSUPPORTED;
1844 		}
1845 		memcpy(&File2,File,sizeof(GSM_File));
1846 		CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1847 		error = N6510_SetFileAttributes1(s,&File2);
1848 		CopyUnicodeString(buf,File->ID_FullName);
1849 		memcpy(File,&File2,sizeof(GSM_File));
1850 		CopyUnicodeString(File->ID_FullName,buf);
1851 		return error;
1852 	} else {
1853 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1854 			return N6510_SetFileAttributes2(s,File);
1855 		} else {
1856 			return ERR_NOTSUPPORTED;
1857 		}
1858 	}
1859 }
1860 
N6510_GetNextRootFolder(GSM_StateMachine * s,GSM_File * File)1861 GSM_Error N6510_GetNextRootFolder(GSM_StateMachine *s, GSM_File *File)
1862 {
1863 	GSM_Error 		error;
1864 	GSM_File  		File2;
1865 	unsigned char		buffer[5];
1866 
1867 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
1868 
1869 	memset(&File2, 0, sizeof(File2));
1870 
1871 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30) ||
1872 	    GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILE1)) {
1873 		if (UnicodeLength(File->ID_FullName) == 0) {
1874 			EncodeUnicode(File->ID_FullName,"d:",2);
1875 			EncodeUnicode(File->Name,"D (Permanent_memory 2)",22);
1876 		} else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"d:")) {
1877 			EncodeUnicode(File->ID_FullName,"a:",2);
1878 			error = N6510_GetFolderListing2(s, File, TRUE);
1879 			if (error != ERR_NONE && error != ERR_EMPTY) return ERR_EMPTY;
1880 			EncodeUnicode(File->Name,"A (Memory card)",15);
1881 			EncodeUnicode(File->ID_FullName,"a:",2);
1882 		} else {
1883 			return ERR_EMPTY;
1884 		}
1885 		return ERR_NONE;
1886 	}
1887 
1888 	if (UnicodeLength(File->ID_FullName) == 0) {
1889 		sprintf(buffer,"%i",0x01);
1890 		EncodeUnicode(File2.ID_FullName,buffer,strlen(buffer));
1891 		File2.Level = 1;
1892 
1893 		error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
1894 		if (error != ERR_NONE) return error;
1895 	}
1896 
1897 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
1898 		if (UnicodeLength(File->ID_FullName) == 0) {
1899 			memcpy(File,&File2,sizeof(GSM_File));
1900 			EncodeUnicode(File->Name,"C (",3);
1901 			CopyUnicodeString(File->Name+6,File2.Name);
1902 			EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1903 			sprintf(buffer,"c:\\%i",0x01);
1904 			EncodeUnicode(File->ID_FullName,buffer,strlen(buffer));
1905 		} else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"c:\\1")) {
1906 			EncodeUnicode(File->ID_FullName,"d:",2);
1907 			EncodeUnicode(File->Name,"D (Permanent_memory 2)",22);
1908 		} else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"d:")) {
1909 			EncodeUnicode(File->ID_FullName,"a:",2);
1910 			error = N6510_GetFolderListing2(s, File, TRUE);
1911 			if (error != ERR_NONE && error != ERR_EMPTY) return ERR_EMPTY;
1912 			EncodeUnicode(File->Name,"A (Memory card)",15);
1913 			EncodeUnicode(File->ID_FullName,"a:",2);
1914 		} else {
1915 			return ERR_EMPTY;
1916 		}
1917 		return ERR_NONE;
1918 	}
1919 	if (UnicodeLength(File->ID_FullName) == 0) {
1920 		memcpy(File,&File2,sizeof(GSM_File));
1921 		EncodeUnicode(File->Name,"C (",3);
1922 		CopyUnicodeString(File->Name+6,File2.Name);
1923 		EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1924 		sprintf(buffer,"c:\\%i",0x01);
1925 		EncodeUnicode(File->ID_FullName,buffer,strlen(buffer));
1926 	} else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"c:\\1")) {
1927 		return ERR_EMPTY;
1928 	}
1929 	return ERR_NONE;
1930 }
1931 
N6510_PrivGet3220FilesystemMMSFolders(GSM_StateMachine * s,GSM_MMSFolders * folders)1932 GSM_Error N6510_PrivGet3220FilesystemMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
1933 {
1934 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1935 	gboolean 			Start = TRUE;
1936 	GSM_File	 	Files;
1937 	GSM_Error		error;
1938 
1939 	memset(&Files, 0, sizeof(Files));
1940 
1941 	EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
1942 
1943 	folders->Number = 0;
1944 
1945 	smprintf(s, "Getting MMS folders\n");
1946 	while (1) {
1947 		error = N6510_GetFolderListing(s,&Files,Start);
1948 		if (error == ERR_EMPTY) return ERR_NONE;
1949 		if (error != ERR_NONE) return error;
1950 
1951 		Start = FALSE;
1952 
1953 		folders->Folder[folders->Number].InboxFolder = FALSE;
1954 		if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
1955 			folders->Folder[folders->Number].InboxFolder = TRUE;
1956 		}
1957 
1958 		CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
1959 
1960 		if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
1961 			EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
1962 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
1963 			EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
1964 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
1965 			EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
1966 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
1967 			EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
1968 		} else {
1969 			continue;
1970 		}
1971 
1972 		folders->Number++;
1973 	}
1974 }
1975 
1976 /* Series 40 3.0 */
N6510_PrivGetFilesystemMMSFolders(GSM_StateMachine * s,GSM_MMSFolders * folders)1977 GSM_Error N6510_PrivGetFilesystemMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
1978 {
1979 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
1980 	gboolean 			Start = TRUE;
1981 	GSM_File	 	Files;
1982 	GSM_Error		error;
1983 
1984 	memset(&Files, 0, sizeof(Files));
1985 
1986 	EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
1987 
1988 	folders->Number = 0;
1989 
1990 	smprintf(s, "Getting MMS folders\n");
1991 	while (1) {
1992 		error = N6510_GetFolderListing(s,&Files,Start);
1993 		if (error == ERR_EMPTY) return ERR_NONE;
1994 		if (error != ERR_NONE) return error;
1995 
1996 		Start = FALSE;
1997 
1998 		if (!strcmp(DecodeUnicodeString(Files.Name),"exchange")) {
1999 			continue;
2000 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2001 			continue;
2002 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2003 			continue;
2004 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2005 			continue;
2006 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2007 			continue;
2008 		}
2009 
2010 		folders->Folder[folders->Number].InboxFolder = FALSE;
2011 		if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2012 			folders->Folder[folders->Number].InboxFolder = TRUE;
2013 		}
2014 
2015 		CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2016 
2017 		if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2018 			EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2019 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"3")) {
2020 			EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2021 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"4")) {
2022 			EncodeUnicode(folders->Folder[folders->Number].Name,"Saved messages",14);
2023 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"5")) {
2024 			EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2025 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"6")) {
2026 			EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
2027 		} else {
2028 			CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2029 		}
2030 
2031 		folders->Number++;
2032 	}
2033 }
2034 
N6510_GetMMSFolders(GSM_StateMachine * s,GSM_MMSFolders * folders)2035 GSM_Error N6510_GetMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
2036 {
2037 	GSM_Error 		error;
2038 	GSM_File  		Files;
2039 	gboolean			Start = TRUE;
2040 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
2041 	int			i;
2042 
2043 
2044 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
2045 
2046 	memset(&Files, 0, sizeof(Files));
2047 
2048 	for (i=0;i<10;i++) {
2049 		Priv->MMSFoldersID2[i][0] = 0;
2050 		Priv->MMSFoldersID2[i][1] = 0;
2051 	}
2052 
2053 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_3220_MMS)) {
2054 		return N6510_PrivGet3220FilesystemMMSFolders(s,folders);
2055 	}
2056 
2057 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30)) {
2058 		return N6510_PrivGetFilesystemMMSFolders(s,folders);
2059 	}
2060 
2061 	EncodeUnicode(Files.ID_FullName,"c:/1",4);
2062 	while (1) {
2063 		error = N6510_GetFolderListing(s,&Files,Start);
2064 		if (error == ERR_EMPTY) break;
2065 		if (error != ERR_NONE) return error;
2066 		Start = FALSE;
2067 		if (!Files.Folder || strcmp(DecodeUnicodeConsole(Files.Name),"Messages")) {
2068 			continue;
2069 		}
2070 		Start 		= TRUE;
2071 		folders->Number = 0;
2072 
2073 		while (1) {
2074 			error = N6510_GetFolderListing(s,&Files,Start);
2075 			if (error == ERR_EMPTY) return ERR_NONE;
2076 			if (error != ERR_NONE) return error;
2077 			Start = FALSE;
2078 			if (!Files.Folder) continue;
2079 			CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2080 			CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2081 			folders->Folder[folders->Number].InboxFolder = FALSE;
2082 			if (!strcmp(DecodeUnicodeString(Files.Name),"Inbox")) {
2083 				folders->Folder[folders->Number].InboxFolder = TRUE;
2084 			}
2085 			folders->Number++;
2086 		}
2087 	}
2088 
2089 	/* 6230i */
2090 	if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_FILES2)) {
2091 		EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
2092 		folders->Number = 0;
2093 		Start 		= TRUE;
2094 		while (1) {
2095 			error = N6510_GetFolderListing(s,&Files,Start);
2096 			if (error == ERR_EMPTY) break;
2097 			if (error != ERR_NONE) return error;
2098 			Start = FALSE;
2099 			if (!Files.Folder) continue;
2100 			folders->Folder[folders->Number].InboxFolder = FALSE;
2101 			if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2102 				EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2103 				folders->Folder[folders->Number].InboxFolder = TRUE;
2104 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2105 				EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
2106 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2107 				EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2108 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2109 				EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2110 			} else {
2111 				CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2112 			}
2113 			CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2114 			folders->Number++;
2115 		}
2116 
2117 		return ERR_NONE;
2118 	}
2119 
2120 	return ERR_NOTSUPPORTED;
2121 }
2122 
N6510_GetNextMMSFileInfo(GSM_StateMachine * s,unsigned char * FileID,int * MMSFolder,gboolean start)2123 GSM_Error N6510_GetNextMMSFileInfo(GSM_StateMachine *s, unsigned char *FileID, int *MMSFolder, gboolean start)
2124 {
2125 	GSM_MMSFolders 		folders;
2126 	GSM_Phone_N6510Data     *Priv = &s->Phone.Data.Priv.N6510;
2127 	GSM_Error		error;
2128 	GSM_File		file;
2129 	int			Handle;
2130 	size_t			Size;
2131 
2132 	if (start) {
2133 		error = N6510_GetMMSFolders(s, &folders);
2134 		if (error != ERR_NONE)
2135 			return error;
2136 
2137 		Priv->MMSFolderNum 	= 0;
2138 		Priv->MMSFolderError 	= ERR_EMPTY;
2139 	}
2140 
2141 	while(TRUE) {
2142 		if (Priv->MMSFolderError == ERR_NONE) {
2143 			Priv->MMSFolderError = N6510_GetFolderListing(s,&Priv->MMSFile,FALSE);
2144 			if (Priv->MMSFolderError != ERR_EMPTY && Priv->MMSFolderError != ERR_NONE)
2145 				return Priv->MMSFolderError;
2146 		}
2147 
2148 		if (Priv->MMSFolderError == ERR_EMPTY) {
2149 			while (1) {
2150 				if (UnicodeLength(Priv->MMSFoldersID2[Priv->MMSFolderNum]) == 0)
2151 					return ERR_EMPTY;
2152 
2153 				CopyUnicodeString(Priv->MMSFile.ID_FullName,Priv->MMSFoldersID2[Priv->MMSFolderNum]);
2154 				Priv->MMSFolderNum++;
2155 
2156 				Priv->MMSFolderError = N6510_GetFolderListing(s,&Priv->MMSFile,TRUE);
2157 				if (Priv->MMSFolderError == ERR_EMPTY)
2158 					continue;
2159 				if (Priv->MMSFolderError != ERR_NONE)
2160 					return Priv->MMSFolderError;
2161 				break;
2162 			}
2163 		}
2164 		(*MMSFolder) = Priv->MMSFolderNum;
2165 		CopyUnicodeString(FileID,Priv->MMSFile.ID_FullName);
2166 
2167 		if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SERIES40_30)) {
2168 			CopyUnicodeString(file.ID_FullName,FileID);
2169 			file.Used   = 0;
2170 			file.Buffer = NULL;
2171 			error = N6510_GetFilePart2(s, &file, &Handle, &Size);
2172 			if (error == ERR_NONE) {
2173 				error = N6510_CloseFile2(s, &Handle);
2174 				if (error != ERR_NONE)
2175 					return error;
2176 			} else if (error != ERR_EMPTY) {
2177 				return error;
2178 			}
2179 
2180 			/* 0x00 = SMS, 0x01,0x03 = MMS */
2181 			if (file.Buffer[6] != 0x00) {
2182 				free(file.Buffer);
2183 				file.Buffer = NULL;
2184 				break;
2185 			}
2186 			free(file.Buffer);
2187 			file.Buffer = NULL;
2188 		} else {
2189 			break;
2190 		}
2191 	}
2192 
2193 	return ERR_NONE;
2194 }
2195 
2196 /* Series 40 3.0 */
N6510_PrivGetFilesystemSMSFolders(GSM_StateMachine * s,GSM_SMSFolders * folders,gboolean real)2197 GSM_Error N6510_PrivGetFilesystemSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders, gboolean real)
2198 {
2199 	gboolean 			Start = TRUE;
2200 	GSM_File	 	Files;
2201 	GSM_Error		error;
2202 
2203 	EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
2204 
2205 	folders->Number = 0;
2206 
2207 	smprintf(s, "Getting SMS folders\n");
2208 	while (1) {
2209 		error = N6510_GetFolderListing(s,&Files,Start);
2210 		if (error == ERR_EMPTY) return ERR_NONE;
2211 		if (error != ERR_NONE) return error;
2212 
2213 		Start = FALSE;
2214 
2215 		smprintf(s, "Folder name: '%s'\n", DecodeUnicodeString(Files.Name));
2216 
2217 		if (!strcmp(DecodeUnicodeString(Files.Name),"exchange")) {
2218 			continue;
2219 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2220 			continue;
2221 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2222 			continue;
2223 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2224 			continue;
2225 		} else if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2226 			continue;
2227 		}
2228 
2229 		folders->Folder[folders->Number].InboxFolder = FALSE;
2230 		if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2231 			folders->Folder[folders->Number].InboxFolder = TRUE;
2232 		}
2233 		folders->Folder[folders->Number].OutboxFolder = FALSE;
2234 		if (!strcmp(DecodeUnicodeString(Files.Name),"2")) {
2235 			folders->Folder[folders->Number].OutboxFolder = TRUE;
2236 		}
2237 		if (real) {
2238 			CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2239 		} else {
2240 			if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2241 				EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2242 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"2")) {
2243 				EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
2244 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"3")) {
2245 				EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2246 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"4")) {
2247 				EncodeUnicode(folders->Folder[folders->Number].Name,"Saved messages",14);
2248 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"5")) {
2249 				EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2250 			} else if (!strcmp(DecodeUnicodeString(Files.Name),"6")) {
2251 				EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
2252 			} else {
2253 				EncodeUnicode(folders->Folder[folders->Number].Name,"User folder ",12);
2254 				CopyUnicodeString(folders->Folder[folders->Number].Name + 24, Files.Name);
2255 			}
2256 		}
2257 		folders->Folder[folders->Number].Memory      = MEM_ME;
2258 		smprintf(s, "Folder[%d] = \"%s\", memory: %s, inbox: %d, outbox: %d\n",
2259 			folders->Number,
2260 			DecodeUnicodeString(folders->Folder[folders->Number].Name),
2261 			GSM_MemoryTypeToString(folders->Folder[folders->Number].Memory),
2262 			folders->Folder[folders->Number].InboxFolder,
2263 			folders->Folder[folders->Number].OutboxFolder);
2264 		folders->Number++;
2265 	}
2266 }
2267 
2268 /* Series 40 3.0 */
N6510_GetFilesystemSMSFolders(GSM_StateMachine * s,GSM_SMSFolders * folders)2269 GSM_Error N6510_GetFilesystemSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
2270 {
2271 	return N6510_PrivGetFilesystemSMSFolders(s, folders, FALSE);
2272 }
2273 
2274 /* Series 40 3.0 */
N26510_GetSMSLocation(GSM_StateMachine * s,GSM_SMSMessage * sms,unsigned char * folderid,int * location)2275 static void N26510_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
2276 {
2277 	int ifolderid;
2278 
2279 	/* simulate flat SMS memory */
2280 	if (sms->Folder==0x00) {
2281 		ifolderid = sms->Location / GSM_PHONE_MAXSMSINFOLDER;
2282 		*folderid = ifolderid + 0x01;
2283 		*location = sms->Location - ifolderid * GSM_PHONE_MAXSMSINFOLDER;
2284 	} else {
2285 		*folderid = sms->Folder;
2286 		*location = sms->Location;
2287 	}
2288 	smprintf(s, "SMS folder %i & location %i -> 6510 folder %i & location %i\n",
2289 		sms->Folder,sms->Location,*folderid,*location);
2290 }
2291 
2292 /* Series 40 3.0 */
N26510_SetSMSLocation(GSM_StateMachine * s,GSM_SMSMessage * sms,unsigned char folderid,int location)2293 static void N26510_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
2294 {
2295 	sms->Folder	= 0;
2296 	sms->Location	= (folderid - 0x01) * GSM_PHONE_MAXSMSINFOLDER + location;
2297 	smprintf(s, "6510 folder %i & location %i -> SMS folder %i & location %i\n",
2298 		folderid,location,sms->Folder,sms->Location);
2299 }
2300 
2301 /* Series 40 3.0 */
N6510_DecodeFilesystemSMS(GSM_StateMachine * s,GSM_MultiSMSMessage * sms,GSM_File * FFF,int location)2302 GSM_Error N6510_DecodeFilesystemSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, GSM_File *FFF, int location)
2303 {
2304 	GSM_Phone_N6510Data	*Priv = &s->Phone.Data.Priv.N6510;
2305 	size_t parse_len, pos;
2306 	int loc;
2307 	GSM_Error error;
2308 	gboolean unknown, has_number;
2309 
2310 	sms->Number = 1;
2311 	sms->SMS[0].OtherNumbersNum = 0;
2312 
2313 	loc = sms->SMS[0].Location;
2314 
2315 	if (FFF->Used < 96) {
2316 		smprintf(s, "Too short message data!\n");
2317 		return ERR_CORRUPTED;
2318 	}
2319 
2320 	/* Copy recipient/sender number */
2321 	/* Data we get from PDU seem to be bogus */
2322 	/* This might be later overwriten using tags at the end of file */
2323 	CopyUnicodeString(sms->SMS[0].Number, FFF->Buffer + 94);
2324 	smprintf(s, "SMS number: %s\n", DecodeUnicodeString(sms->SMS[0].Number));
2325 	has_number = FALSE;
2326 
2327 	/* Do we have any PDU data? */
2328 	if (FFF->Buffer[7] > 0 && FFF->Used > 176) {
2329 		/* Parse PDU data */
2330 		error = GSM_DecodePDUFrame(&(s->di), &(sms->SMS[0]),  FFF->Buffer + 176, FFF->Used - 176, &parse_len, FALSE);
2331 		if (error != ERR_NONE) return error;
2332 
2333 		sms->SMS[0].Location = loc;
2334 
2335 		switch (sms->SMS[0].PDU) {
2336 			case SMS_Deliver:
2337 				sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2338 				break;
2339 			case SMS_Submit:
2340 				sms->SMS[0].State = SMS_Sent; /* @bug FIXME: this is wrong */
2341 				break;
2342 			case SMS_Status_Report:
2343 				sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2344 				break;
2345 		}
2346 
2347 		if (parse_len != FFF->Buffer[7]) {
2348 			smprintf(s, "ERROR: Parsed PDU data have different length than header says!\n");
2349 			return ERR_CORRUPTED;
2350 		}
2351 	} else {
2352 		GSM_SetDefaultReceivedSMSData(&sms->SMS[0]);
2353 		sms->SMS[0].PDU = SMS_Submit;
2354 		sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2355 	}
2356 
2357 	/* Process structured data */
2358 	pos = 176 + FFF->Buffer[7];
2359 
2360 	/* No structured data? */
2361 	if (pos >= FFF->Used) {
2362 		goto done;
2363 	}
2364 
2365 	/* First master block - 0x01 <WORD LENGTH> */
2366 	if (FFF->Buffer[pos] != 0x01) {
2367 		smprintf(s, "Unknown block in SMS data after PDU: 0x%02x\n", FFF->Buffer[pos]);
2368 		DumpMessage(&(s->di), FFF->Buffer + pos, FFF->Used - pos);
2369 		return ERR_UNKNOWN;
2370 	}
2371 	pos += 3;
2372 
2373 	while (pos < FFF->Used) {
2374 		unknown = FALSE;
2375 		if (pos + 1 >= FFF->Used) {
2376 			if (pos + 1 == FFF->Used && FFF->Buffer[pos] == 0x00) {
2377 				smprintf(s, "File padded with 0x00, assuming it is okay\n");
2378 				break;
2379 			}
2380 			smprintf(s, "ERROR: Reach end of file before type of block!\n");
2381 			return ERR_BUG;
2382 		}
2383 		if (FFF->Buffer[pos] == 0x00) {
2384 			smprintf(s, "WARNING: 0x00 block, assuming rest is just junk!\n");
2385 			break;
2386 		}
2387 		if (pos + 2 == FFF->Used && FFF->Buffer[pos] == 0x01) {
2388 			smprintf(s, "WARNING: 0x01 block, assuming rest is just junk!\n");
2389 			break;
2390 		}
2391 		if (pos + 2 >= FFF->Used) {
2392 			smprintf(s, "ERROR: Reach end of file before size of block!\n");
2393 			return ERR_BUG;
2394 		}
2395 		switch (FFF->Buffer[pos]) {
2396 			case 0x02: /* SMSC number, ASCII */
2397 				if (FFF->Buffer[pos + 2] <= 1) break;
2398 				if (FFF->Buffer[pos + 2] - 1 > GSM_MAX_NUMBER_LENGTH) {
2399 					smprintf(s, "WARNING: Too long SMS number, ignoring!\n");
2400 				} else {
2401 					EncodeUnicode(sms->SMS[0].SMSC.Number, FFF->Buffer + pos + 3, FFF->Buffer[pos + 2]);
2402 				}
2403 				break;
2404 			case 0x03: /* Name, unicode */
2405 				if (FFF->Buffer[pos + 2] <= 1) break;
2406 				if (FFF->Buffer[pos + 2]/2 - 1 > GSM_MAX_SMS_NAME_LENGTH) {
2407 					smprintf(s, "WARNING: Too long SMS name, ignoring!\n");
2408 				} else {
2409 					CopyUnicodeString(sms->SMS[0].Name, FFF->Buffer + pos + 3);
2410 				}
2411 				break;
2412 			case 0x04: /* Sender, unicode */
2413 			case 0x05: /* Recipient, unicode */
2414 			case 0x2b: /* some text (Sender?), unicode */
2415 				if (FFF->Buffer[pos + 2] <= 1) break;
2416 				if (FFF->Buffer[pos + 2]/2 - 1 > GSM_MAX_NUMBER_LENGTH) {
2417 					smprintf(s, "WARNING: Too long SMS number, ignoring!\n");
2418 				} else {
2419 					if (!has_number) {
2420 						CopyUnicodeString(sms->SMS[0].Number, FFF->Buffer + pos + 3);
2421 						has_number = TRUE;
2422 					} else {
2423 						if (sms->SMS[0].OtherNumbersNum < GSM_SMS_OTHER_NUMBERS) {
2424 							CopyUnicodeString(sms->SMS[0].OtherNumbers[sms->SMS[0].OtherNumbersNum++], FFF->Buffer + pos + 3);
2425 						} else {
2426 							smprintf(s, "WARNING: Too many recipients, ignoring some!\n");
2427 						}
2428 					}
2429 				}
2430 				break;
2431 			case 0x25: /* Some unicode text (Name?) */
2432 			case 0x20: /* Some ascii text (GmailId) */
2433 				unknown = TRUE;
2434 				break;
2435 			case 0x01:
2436 				/* This is probably 0 = received, 1 = sent */
2437 				if (FFF->Buffer[pos + 2] != 1 ||
2438 					(FFF->Buffer[pos + 3] != 0x00 && FFF->Buffer[pos + 3] != 0x01)) {
2439 					unknown = TRUE;
2440 				}
2441 				break;
2442 			case 0x0c:
2443 				/* This seems to be message ID (per number) */
2444 				break;
2445 			case 0x24:
2446 				/* 24$|00 |01 |01 */
2447 				/* 24$|00 |01 |00 */
2448 				if ((FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 1) &&
2449 					(FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 0)) {
2450 					unknown = TRUE;
2451 				}
2452 				break;
2453 			case 0x07:
2454 				/* 07 |00 |01 |00 */
2455 				if (FFF->Buffer[pos + 2] != 1 || (FFF->Buffer[pos + 3] != 0x0F && FFF->Buffer[pos + 3] != 0x0e && FFF->Buffer[pos + 3] != 0x00)) {
2456 					unknown = TRUE;
2457 				}
2458 				break;
2459 			case 0x0b:
2460 			case 0x0e:
2461 			case 0x22:
2462 				/* 22"|00 |01 |84 */
2463 			case 0x26:
2464 			case 0x27:
2465 			case 0x2a:
2466 			case 0x2f:
2467 			case 0x08:
2468 				if (FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 0x00) {
2469 					unknown = TRUE;
2470 				}
2471 				break;
2472 			case 0x06:
2473 			case 0x09:
2474 			case 0x12:
2475 				/* Some ID: 12 |00 |04 |355|EA |6En|D2 */
2476 			case 0x23:
2477 				/* Some ID: 23#|00 |04 |00 |00 |09 |A6 */
2478 			case 0x2D:
2479 				/* Some ID: 2D-|00 |04 |00 |00 |00 |00 */
2480 				if (FFF->Buffer[pos + 2] != 4 ||
2481 					FFF->Buffer[pos + 3] != 0x00 ||
2482 					FFF->Buffer[pos + 4] != 0x00 ||
2483 					FFF->Buffer[pos + 5] != 0x00 ||
2484 					FFF->Buffer[pos + 6] != 0x00
2485 					) {
2486 					unknown = TRUE;
2487 				}
2488 				break;
2489 			case 0x0f:
2490 				if (FFF->Buffer[pos + 2] != 2 ||
2491 					FFF->Buffer[pos + 3] != 0x00 ||
2492 					FFF->Buffer[pos + 4] != 0x00
2493 					) {
2494 					unknown = TRUE;
2495 				}
2496 				break;
2497 			default:
2498 				unknown = TRUE;
2499 				break;
2500 		}
2501 		if (unknown) {
2502 			smprintf(s, "WARNING: Unknown block 0x%02x, see <https://wammu.eu/support/bugs/> how to report\n", FFF->Buffer[pos]);
2503 			DumpMessage(&(s->di), FFF->Buffer + pos, 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2]);
2504 #ifdef DEBUG
2505 		} else {
2506 			smprintf(s, "Decoded block 0x%02x\n", FFF->Buffer[pos]);
2507 			DumpMessage(&(s->di), FFF->Buffer + pos, 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2]);
2508 #endif
2509 		}
2510 		pos += 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2];
2511 	}
2512 
2513 done:
2514 	sms->SMS[0].DateTime = FFF->Modified;
2515 	sms->SMS[0].DateTime.Timezone = 0;
2516 
2517 	free(FFF->Buffer);
2518 	FFF->Buffer = NULL;
2519 
2520 	N26510_SetSMSLocation(s, &sms->SMS[0], 0, location);
2521 
2522 	sms->SMS[0].Folder = Priv->SMSFileFolder;
2523 	smprintf(s, "Folder[%d] %s: %d\n", sms->SMS[0].Folder, DecodeUnicodeString(Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].Name), Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].InboxFolder);
2524 	sms->SMS[0].InboxFolder = Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].InboxFolder;
2525 	sms->SMS[0].Location = 0; /* fixme */
2526 
2527 	return ERR_NONE;
2528 }
2529 
N6510_GetNextFilesystemSMS(GSM_StateMachine * s,GSM_MultiSMSMessage * sms,gboolean start)2530 GSM_Error N6510_GetNextFilesystemSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, gboolean start)
2531 {
2532 	GSM_Phone_N6510Data	*Priv = &s->Phone.Data.Priv.N6510;
2533 	unsigned char		folderid;
2534 	int			location,Handle;
2535 	size_t			Size;
2536 	GSM_Error		error;
2537 	GSM_File		FFF;
2538 	gboolean			start2=start;
2539 
2540 	GSM_SetDefaultReceivedSMSData(&sms->SMS[0]);
2541 
2542 	while (TRUE) {
2543 		if (start2) {
2544 			Priv->SMSFileError = ERR_EMPTY;
2545 			Priv->SMSFileFolder = 0;
2546 			location = 1;
2547 			error=N6510_PrivGetFilesystemSMSFolders(s,&Priv->LastSMSFolders,TRUE);
2548 			if (error!=ERR_NONE) return error;
2549 		} else {
2550 			sms->SMS[0].Folder = 0;
2551 			N26510_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
2552 			location++;
2553 			if (Priv->SMSFileError != ERR_EMPTY) {
2554 				Priv->SMSFileError = N6510_GetFolderListing(s,&Priv->SMSFile,FALSE);
2555 			}
2556 		}
2557 		start2 = FALSE;
2558 		while (Priv->SMSFileError == ERR_EMPTY) {
2559 			Priv->SMSFileFolder++;
2560 			/* Too high folder number */
2561 			if (Priv->SMSFileFolder > Priv->LastSMSFolders.Number) {
2562 				return ERR_EMPTY;
2563 			}
2564 
2565 			EncodeUnicode(Priv->SMSFile.ID_FullName, "d:/predefmessages/", 18);
2566 			CopyUnicodeString(Priv->SMSFile.ID_FullName + 36, Priv->LastSMSFolders.Folder[Priv->SMSFileFolder-1].Name);
2567 			smprintf(s,"folder name is %s\n", DecodeUnicodeString(Priv->SMSFile.ID_FullName));
2568 
2569 			Priv->SMSFileError = N6510_GetFolderListing(s,&Priv->SMSFile,TRUE);
2570 		}
2571 
2572 		/* readfile */
2573 		FFF.Buffer= NULL;
2574 		FFF.Used = 0;
2575 		FFF.ID_FullName[0] = 0;
2576 		FFF.ID_FullName[1] = 0;
2577 		CopyUnicodeString(FFF.ID_FullName,Priv->SMSFile.ID_FullName);
2578 		smprintf(s,"sms file name is %s\n",DecodeUnicodeString(FFF.ID_FullName));
2579 		error = ERR_NONE;
2580 		while (error == ERR_NONE) {
2581 			error = N6510_GetFilePart(s,&FFF,&Handle,&Size);
2582 			/* if mms, don't read all */
2583 			if (error==ERR_NONE && FFF.Used>5 && FFF.Buffer[6] != 0x00) {
2584 				error = N6510_CloseFile2(s, &Handle);
2585 				if (error != ERR_NONE) return error;
2586 				break;
2587 			}
2588 		}
2589 		if (FFF.Buffer != NULL)  {
2590 			DumpMessage(&s->di, FFF.Buffer, FFF.Used);
2591 
2592 			/* 0x00 = SMS, 0x01,0x03 = MMS
2593 			 * We care only messages with PDU */
2594 			if (FFF.Buffer[6] == 0x00 && FFF.Buffer[7] != 0) break;
2595 
2596 
2597 			smprintf(s,"mms file");
2598 			free(FFF.Buffer);
2599 			FFF.Buffer = NULL;
2600 		}
2601 	}
2602 
2603 	return N6510_DecodeFilesystemSMS(s, sms, &FFF, location);
2604 }
2605 #endif
2606 
2607 /* How should editor hadle tabs in this file? Add editor commands here.
2608  * vim: noexpandtab sw=8 ts=8 sts=8:
2609  */
2610