1 /***************************************************************************
2  *   copyright           : (C) 2004 by Hendrik Sattler                     *
3  *   mail                : post@hendrik-sattler.de                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  ***************************************************************************/
11 
12 #include "pbookphone.h"
13 #include "scmxx.h"
14 #include "helper.h"
15 #include "atcommand.h"
16 #include "gtincl.h"
17 
18 #include <ctype.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <unistd.h>
22 
struct_pbook_phone_entry_init(struct pbook_phone_entry * p)23 void struct_pbook_phone_entry_init (struct pbook_phone_entry* p) {
24   p->slot = 0;
25   p->number = NULL;
26   p->numtype = numtype(NULL);
27   p->text = NULL;
28 }
struct_pbook_phone_entry_delete(struct pbook_phone_entry * p)29 void struct_pbook_phone_entry_delete (struct pbook_phone_entry* p) {
30   mem_realloc(p->number,0);
31   mem_realloc(p->text,0);
32 }
33 
pbook_phone_write_entry(struct pbook_phone_entry * entry)34 int pbook_phone_write_entry (struct pbook_phone_entry* entry) {
35   char* temp;
36   int retval = 1;
37 
38   at_gen_phonebook_write(entry->slot,entry->number,
39 			 entry->numtype,(char*)entry->text);
40   temp = at_read_line();
41   if (at_line_type(temp,NULL,NULL) != AT_RET_OK) retval = 0;
42   mem_realloc(temp,0);
43   return retval;
44 }
45 
pbook_phone_write(char * mem,struct pbook_phone_entry ** entries)46 int pbook_phone_write (char* mem, struct pbook_phone_entry** entries) {
47   unsigned int min,max;
48   int nlen,tlen;
49   unsigned long i = 0;
50   unsigned long count = 0;
51   char* text = NULL;
52 
53   if (!pbook_get_ranges(mem,1,&min,&max,&nlen,&tlen)) {
54     errexit(_("getting limits of phonebook %s failed.\n"),mem);
55   }
56 
57   for (i = 0; entries[i] != NULL; ++i) {
58     if (min > entries[i]->slot || entries[i]->slot > max) {
59       errexit (_("slot %d is out of range %d-%d.\n"),entries[i]->slot,min,max);
60     }
61   }
62   count = i;
63   if (count > max-min+1) {
64     errexit(_("too many entries (max. %d).\n"),max-min+1);
65   }
66 
67   if (count > 1) {
68     print_verbose(0,_("Updating entries %s(%d-%d)...\n"),mem,min,max);
69     text = mem_alloc(str_len(mem)+numlen(max)+3,1);
70     for (i = 1; entries[i-1] != NULL; ++i) {
71       if (pbook_phone_write_entry(entries[i-1]) == 0) return 0;
72       sprintf(text,"%s(%u)",(mem)?mem:"",entries[i-1]->slot);
73       console_print_status(STDERR_FILENO,text,str_len(text),&i,&count,1);
74     }
75     mem_realloc(text,0);
76     console_print_status(STDERR_FILENO,_("done"),strlen(_("done")),&i,&count,1);
77     if (count > 1) print_verbose(0,"%c",'\n');
78   } else {
79     print_verbose(0,_("Updating one entry in slot %d of memory %s..."),entries[0]->slot,mem);
80     if (pbook_phone_write_entry(entries[0]) == 0) return 0;
81   }
82   print_verbose(0,"%s\n",_("done"));
83   return 1;
84 }
85 
86 /* fill the pbook_phone_entry from a text line
87  */
pbook_phone_str2entry(char * line,struct pbook_phone_entry * entry)88 int pbook_phone_str2entry (char* line,
89 			   struct pbook_phone_entry* entry)
90 {
91   //pointers in line
92   char* slot;
93   char* number;
94   char* numtype;
95   char* text;
96 
97   if (line == NULL || entry == NULL) return -1;
98 
99   /* Policy is to not trust in what the phone delivers
100    * Thus, full checking must be done.
101    * Format: slot,"number",numtype,"text"
102    */
103   slot = line;
104   while(isdigit((int)*line) && *line != 0) ++line;
105   if (*line != ',' || *line == 0) return 0;
106   ++line;
107   if (*line != '"' || *line == 0) return 0;
108   number = ++line;
109   while (*line != '"' && *line != 0) ++line;
110   if (*line != '"' || *line == 0) return 0;
111   ++line;
112   if (*line != ',' || *line == 0) return 0;
113   numtype = ++line;
114   while(isdigit((int)*line) && *line != 0) ++line;
115   if (*line != ',' || *line == 0) return 0;
116   ++line;
117   if (*line != '"' || *line == 0) return 0;
118   text = ++line;
119   if ((line=strrchr(text-1,'"')) <= text-1) return 0;
120   ++line;
121   if (*line != 0) return 0;
122 
123   entry->slot = atoi(slot);
124   entry->number = strn_dup(number,strchr(number,'"')-number);
125   entry->numtype = atoi(numtype);
126   entry->text = (unsigned char*)strn_dup(text,strrchr(text,'"')-text);
127   return 1;
128 }
129 
130 /* slot_max-slot_min can be used to loop over a limited range
131  * The returned pointer is malloc'd, NULL-terminated list,
132  * each list enty is malloc'd, too.
133  */
134 #include <unistd.h>
135 struct pbook_phone_entry**
pbook_phone_get_range(char * mem,unsigned int slot_min,unsigned int slot_max,int print_counter)136 pbook_phone_get_range (char* mem,
137 		       unsigned int slot_min,
138 		       unsigned int slot_max,
139 		       int print_counter)
140 {
141   unsigned int i = 0;
142   unsigned range = slot_max-slot_min+1;
143   struct pbook_phone_entry** retval;
144   struct pbook_phone_entry* buffer;
145   struct pbook_phone_entry** vcfbuf;
146   char* command;
147   char* ausgabe;
148   char* temp;
149   enum return_code linestatus;
150   int status;
151   int enable_slot_range_test = 1;
152   unsigned int j,k = 0;
153 
154   if (strcasecmp(mem,VCARD_PHONEBOOK_NAME) == 0)
155     if (slot_min != slot_max) {
156       retval = mem_alloc(((range*4)+1)*sizeof(*retval),0);
157       for (i = slot_min; i <= slot_max; ++i) {
158 	//call this function recursively (one level)
159 	vcfbuf = pbook_phone_get_range(mem,i,i,print_counter);
160 	for (j = 0; vcfbuf[j] != NULL; ++j) {
161 	  retval[k++] = vcfbuf[j];
162 	}
163 	vcfbuf = mem_realloc(vcfbuf,0);
164       }
165       retval[k] = NULL;
166       return retval;
167     } else {
168       command = at_sie_phonebook_vcf_read(slot_min, -1);
169       enable_slot_range_test = 0;
170       range = 4;
171     }
172   else
173     if (strcasecmp(mem,"RD") == 0 || strcasecmp(mem,"CS") == 0)
174       command = at_sie_phonebook_read_sorted(slot_min,slot_max); /* Get sorted pb */
175     else
176       command = at_gen_phonebook_read(slot_min,slot_max); /* Get pb */
177 
178   if (command != NULL) {
179     ausgabe = at_read_line();
180     linestatus = at_line_type(ausgabe,command,&temp);
181   }
182   if (command == NULL || linestatus&AT_RET_ERROR)
183     errexit(_("reading from phonebook %s failed: %s\n"),mem,temp);
184 
185   retval = mem_alloc((range+1)*sizeof(*retval),0);
186   while ((linestatus == AT_RET_ANSWER ||
187 	  linestatus == AT_RET_OTHER) &&
188 	 i <= i+range-1) {
189     buffer = mem_alloc(sizeof(**retval),0);
190     struct_pbook_phone_entry_init(buffer);
191     status = pbook_phone_str2entry(temp,buffer);
192     if (status <= 0) errexit(_("parsing entry failed: %s\n"), temp);
193 
194     if (enable_slot_range_test) {
195       if (buffer->slot > slot_max) errexit(_("phone returned unexpected entry %u\n"),buffer->slot);
196       for (; i+slot_min < buffer->slot; ++i) {
197 	retval[i] = mem_alloc(sizeof(**retval),0);
198 	struct_pbook_phone_entry_init(retval[i]);
199 	retval[i]->slot = i+slot_min;
200 	if (verbosity_get() < VERBOSE_LEVEL_NOTICE && print_counter)
201 	  print_verbose(0," %d",retval[i]->slot);
202       }
203     }
204     retval[i] = buffer;
205     if (strcasecmp(mem,VCARD_PHONEBOOK_NAME) == 0) retval[i]->slot = slot_min;
206     if (verbosity_get() < VERBOSE_LEVEL_NOTICE && print_counter)
207       print_verbose(0," %d",retval[i]->slot);
208 
209     mem_realloc(ausgabe,0);
210     ausgabe = at_read_line();
211     linestatus = at_line_type(ausgabe,command,&temp);
212     if (linestatus&AT_RET_ERROR) errexit(_("reading from phonebook %s failed: %s\n"),mem,temp);
213     ++i;
214   }
215   if (enable_slot_range_test) {
216     for (; i+slot_min <= slot_max; ++i) {
217       retval[i] = mem_alloc(sizeof(**retval),0);
218       struct_pbook_phone_entry_init(retval[i]);
219       retval[i]->slot = i+slot_min;
220       if (verbosity_get() < VERBOSE_LEVEL_NOTICE && print_counter)
221 	print_verbose(0," %d",retval[i]->slot);
222     }
223   }
224   retval[i] = NULL; //termination of list
225   return retval;
226 }
227 
228 // number of requested number during a search
229 #define search_delta 5
230 
pbook_phone_find_empty(char * mem,unsigned int startslot)231 int pbook_phone_find_empty (char* mem, unsigned int startslot) {
232   unsigned int min = -1, max = -1;
233   unsigned int tempmax;
234   int retval = -1;
235   unsigned int i;
236   struct pbook_phone_entry** temp;
237 
238   //reading available indexes
239   if (!pbook_get_ranges(mem,0,&min,&max,NULL,NULL)) {
240     errexit(_("getting limits of phonebook %s failed.\n"),mem);
241   }
242   if ((min == (unsigned int)0 && max == (unsigned int)0) ||
243       startslot > max)
244   {
245     //emty phonebook
246     return -1;
247   }
248 
249   print_verbose(0,"%s\n",_("Trying to find an empty slot..."));
250   if (startslot < min) startslot = min;
251   for (;startslot <= max && retval < 0; startslot += search_delta ) {
252     tempmax = startslot+search_delta-1;
253     if (tempmax > max) tempmax = max;
254     temp = pbook_phone_get_range(mem,startslot,tempmax,0);
255     for (i=0; temp[i] != NULL; ++i) {
256       if (str_len(temp[i]->number) == 0 &&
257 	  str_len((char*)temp[i]->text) == 0 &&
258 	  retval < 0) {
259 	retval = temp[i]->slot;
260 	print_verbose(0,_("Detected empty slot %d\n"),retval);
261       }
262       struct_pbook_phone_entry_delete(temp[i]);
263     }
264     mem_realloc(temp,0);
265   }
266   return retval;
267 }
268 
269 /* number of requesting numbers
270  * higher means a little bit more speed
271  * lower helps slow phones/SIM-cards to not time out
272  */
273 #define delta 5
274 
275 struct pbook_phone_entry**
pbook_phone_get(char * mem)276 pbook_phone_get (char* mem) {
277   unsigned cur_min, cur_max;
278   unsigned int min = -1, max = -1;
279   struct pbook_phone_entry** retval;
280   struct pbook_phone_entry** temp;
281   unsigned long i,j; //index in temp
282   unsigned int k = 0; //index in retval
283   char* text = NULL;
284 
285   //reading available indexes
286   if (!pbook_get_ranges(mem,0,&min,&max,NULL,NULL)) {
287     errexit(_("getting limits of phonebook %s failed.\n"),mem);
288   }
289   if (min == 0 && max == 0) {
290     //emty phonebook
291     return NULL;
292   }
293   text = mem_alloc(str_len(mem)+numlen(min)+numlen(max)+4,1);
294   sprintf(text,"%s(%d-%d)",mem,min,max);
295   print_verbose(0,"%s\n",_("Receiving phonebook entries..."));
296   //4 times as big due to phonebook vcf
297   retval = mem_alloc(((4*(max-min+1))+1)*sizeof(*retval),0);
298   retval[0] = NULL;
299   for (cur_min = min; cur_min <= (unsigned int)max; cur_min += delta) {
300     cur_max = cur_min+delta-1;
301     if (cur_max > (unsigned int)max) cur_max = max;
302     i = cur_min-min;
303     j = max-min+1;
304     console_print_status(STDERR_FILENO,text,str_len(text),&i,&j,1);
305     temp = pbook_phone_get_range(mem,cur_min,cur_max,0);
306     i = 0;
307     while (temp[i] != NULL) retval[k++] = temp[i++];
308     retval[k] = NULL;
309   }
310   i = max;
311   console_print_status(STDERR_FILENO,text,str_len(text),&i,&i,1);
312   mem_realloc(text,0);
313   print_verbose(0,"%c",'\n');
314   return retval;
315 }
316