]> Dogcows Code - chaz/homebank/blob - src/hb-xml.c
Merge branch 'upstream'
[chaz/homebank] / src / hb-xml.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "hb-transaction.h"
24 #include "hb-xml.h"
25
26 #include "ui-dialogs.h"
27
28 /****************************************************************************/
29 /* Debug macros */
30 /****************************************************************************/
31 #define MYDEBUG 0
32
33 #if MYDEBUG
34 #define DB(x) (x);
35 #else
36 #define DB(x);
37 #endif
38
39 /* our global datas */
40 extern struct HomeBank *GLOBALS;
41 extern struct Preferences *PREFS;
42
43
44 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
45
46
47 // v0.1 to v0.2 : we must change account reference by making a +1 to its index references
48 static void homebank_upgrade_to_v02(void)
49 {
50 GList *lst_acc, *lnk_acc;
51 GList *list;
52 GHashTable *h_old_acc;
53
54
55 DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") );
56
57 //keep old hashtable with us
58 h_old_acc = GLOBALS->h_acc;
59 da_acc_new();
60
61 lst_acc = g_hash_table_get_values(h_old_acc);
62 lnk_acc = g_list_first(lst_acc);
63 while (lnk_acc != NULL)
64 {
65 Account *acc = lnk_acc->data;
66
67 acc->key++;
68 acc->pos++;
69 da_acc_insert (acc);
70
71 list = g_queue_peek_head_link(acc->txn_queue);
72 while (list != NULL)
73 {
74 Transaction *entry = list->data;
75 entry->kacc++;
76 entry->kxferacc++;
77 list = g_list_next(list);
78 }
79 lnk_acc = g_list_next(lnk_acc);
80 }
81 g_list_free(lst_acc);
82
83 //we loose some small memory here
84 g_hash_table_steal_all(h_old_acc);
85
86 list = g_list_first(GLOBALS->arc_list);
87 while (list != NULL)
88 {
89 Archive *entry = list->data;
90 entry->kacc++;
91 entry->kxferacc++;
92 list = g_list_next(list);
93 }
94 }
95
96 // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738
97 static void homebank_upgrade_to_v03(void)
98 {
99 GList *lst_acc, *lnk_acc;
100 GList *list;
101
102 DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") );
103
104 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
105 lnk_acc = g_list_first(lst_acc);
106 while (lnk_acc != NULL)
107 {
108 Account *acc = lnk_acc->data;
109
110 list = g_queue_peek_head_link(acc->txn_queue);
111 while (list != NULL)
112 {
113 Transaction *entry = list->data;
114
115 da_transaction_consistency(entry);
116 list = g_list_next(list);
117 }
118 lnk_acc = g_list_next(lnk_acc);
119 }
120 g_list_free(lst_acc);
121
122
123 list = g_list_first(GLOBALS->arc_list);
124 while (list != NULL)
125 {
126 Archive *entry = list->data;
127
128 da_archive_consistency(entry);
129 list = g_list_next(list);
130 }
131 }
132
133 static void homebank_upgrade_to_v04(void)
134 {
135 DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") );
136
137 GLOBALS->arc_list = da_archive_sort(GLOBALS->arc_list);
138 }
139
140
141 // v0.4 to v0.5 :
142 // we must assume kxferacc exists in archives for internal xfer : bug 528923
143 // if not, delete automation from the archive
144 static void homebank_upgrade_to_v05(void)
145 {
146 GList *list;
147
148 DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") );
149
150 list = g_list_first(GLOBALS->arc_list);
151 while (list != NULL)
152 {
153 Archive *entry = list->data;
154
155 da_archive_consistency(entry);
156 list = g_list_next(list);
157 }
158 }
159
160
161 // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions
162 //#677351
163 static void homebank_upgrade_to_v06(void)
164 {
165 GList *lst_acc, *lnk_acc;
166 GList *list;
167
168 DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") );
169
170 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
171 lnk_acc = g_list_first(lst_acc);
172 while (lnk_acc != NULL)
173 {
174 Account *acc = lnk_acc->data;
175
176 list = g_queue_peek_head_link(acc->txn_queue);
177 while (list != NULL)
178 {
179 Transaction *entry = list->data;
180 da_transaction_consistency(entry);
181 list = g_list_next(list);
182 }
183 lnk_acc = g_list_next(lnk_acc);
184 }
185 g_list_free(lst_acc);
186
187
188 list = g_list_first(GLOBALS->arc_list);
189 while (list != NULL)
190 {
191 Archive *entry = list->data;
192 da_archive_consistency(entry);
193 list = g_list_next(list);
194 }
195 }
196
197
198 // v0.7 AF_BUDGET deleted instead of AF_NOBUDGET
199 static void homebank_upgrade_to_v07(void)
200 {
201 GList *lacc, *list;
202
203 DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") );
204
205 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
206 while (list != NULL)
207 {
208 Account *acc = list->data;
209
210 if( acc->flags & AF_OLDBUDGET ) // budget include
211 {
212 acc->flags &= ~(AF_OLDBUDGET);
213 }
214 else
215 {
216 acc->flags |= AF_NOBUDGET;
217 }
218
219 list = g_list_next(list);
220 }
221 g_list_free(lacc);
222
223 }
224
225 static void homebank_upgrade_to_v08(void)
226 {
227 GList *lst_acc, *lnk_acc;
228 GList *list;
229
230 DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") );
231
232 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
233 lnk_acc = g_list_first(lst_acc);
234 while (lnk_acc != NULL)
235 {
236 Account *acc = lnk_acc->data;
237
238 list = g_queue_peek_head_link(acc->txn_queue);
239 while (list != NULL)
240 {
241 Transaction *entry = list->data;
242 da_transaction_consistency(entry);
243 list = g_list_next(list);
244 }
245 lnk_acc = g_list_next(lnk_acc);
246 }
247 g_list_free(lst_acc);
248
249
250 }
251
252
253 static void homebank_upgrade_to_v10(void)
254 {
255 GList *lst_acc, *lnk_acc;
256 GList *list;
257
258 DB( g_print("\n[hb-xml] homebank_upgrade_to_v10\n") );
259
260 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
261 lnk_acc = g_list_first(lst_acc);
262 while (lnk_acc != NULL)
263 {
264 Account *acc = lnk_acc->data;
265
266 list = g_queue_peek_head_link(acc->txn_queue);
267 while (list != NULL)
268 {
269 Transaction *entry = list->data;
270
271 entry->status = TXN_STATUS_NONE;
272 if(entry->flags & OF_OLDVALID)
273 entry->status = TXN_STATUS_RECONCILED;
274 else
275 if(entry->flags & OF_OLDREMIND)
276 entry->status = TXN_STATUS_REMIND;
277
278 //remove those flags
279 entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND);
280
281 list = g_list_next(list);
282 }
283 lnk_acc = g_list_next(lnk_acc);
284 }
285 g_list_free(lst_acc);
286
287 }
288
289
290 static void homebank_upgrade_to_v11(void)
291 {
292 GList *list;
293
294 DB( g_print("\n[hb-xml] homebank_upgrade_to_v11\n") );
295
296 list = g_list_first(GLOBALS->arc_list);
297 while (list != NULL)
298 {
299 Archive *entry = list->data;
300
301 entry->status = TXN_STATUS_NONE;
302 if(entry->flags & OF_OLDVALID)
303 entry->status = TXN_STATUS_RECONCILED;
304 else
305 if(entry->flags & OF_OLDREMIND)
306 entry->status = TXN_STATUS_REMIND;
307
308 //remove those flags
309 entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND);
310
311 list = g_list_next(list);
312 }
313
314 }
315
316
317 // v0.6 to v0.7 : assign a default currency
318 static void homebank_upgrade_to_v12(void)
319 {
320 // set a base currency to the hbfile if not
321 DB( g_print("GLOBALS->kcur %d\n", GLOBALS->kcur) );
322
323 ui_dialog_upgrade_choose_currency();
324 }
325
326
327
328 // lower v0.6 : we must assume categories/payee exists
329 // and strong link to xfer
330 // #632496
331 static void homebank_upgrade_lower_v06(void)
332 {
333 GList *lst_acc, *lnk_acc;
334 Category *cat;
335 Payee *pay;
336 GList *lrul, *list;
337
338 DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") );
339
340 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
341 lnk_acc = g_list_first(lst_acc);
342 while (lnk_acc != NULL)
343 {
344 Account *acc = lnk_acc->data;
345
346 list = g_queue_peek_head_link(acc->txn_queue);
347 while (list != NULL)
348 {
349 Transaction *entry = list->data;
350
351 //also strong link internal xfer
352 if(entry->paymode == PAYMODE_INTXFER && entry->kxfer == 0)
353 {
354 Transaction *child = transaction_old_get_child_transfer(entry);
355 if(child != NULL)
356 {
357 transaction_xfer_change_to_child(entry, child);
358 }
359 }
360
361 da_transaction_consistency(entry);
362
363 list = g_list_next(list);
364 }
365 lnk_acc = g_list_next(lnk_acc);
366 }
367 g_list_free(lst_acc);
368
369
370 lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
371 while (list != NULL)
372 {
373 Assign *entry = list->data;
374
375 cat = da_cat_get(entry->kcat);
376 if(cat == NULL)
377 {
378 DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) );
379 entry->kcat = 0;
380 }
381
382 pay = da_pay_get(entry->kpay);
383 if(pay == NULL)
384 {
385 DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) );
386 entry->kpay = 0;
387 }
388
389
390 list = g_list_next(list);
391 }
392 g_list_free(lrul);
393 }
394
395
396 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
397
398
399 static void homebank_load_xml_acc(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
400 {
401 Account *entry = da_acc_malloc();
402 gint i;
403
404 for (i = 0; attribute_names[i] != NULL; i++)
405 {
406 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
407
408 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
409 else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
410 else if(!strcmp (attribute_names[i], "pos" )) { entry->pos = atoi(attribute_values[i]); }
411 else if(!strcmp (attribute_names[i], "type" )) { entry->type = atoi(attribute_values[i]); }
412 else if(!strcmp (attribute_names[i], "curr" )) { entry->kcur = atoi(attribute_values[i]); }
413 else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); }
414 else if(!strcmp (attribute_names[i], "number" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->number = g_strdup(attribute_values[i]); }
415 else if(!strcmp (attribute_names[i], "bankname")) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->bankname = g_strdup(attribute_values[i]); }
416 else if(!strcmp (attribute_names[i], "initial" )) { entry->initial = g_ascii_strtod(attribute_values[i], NULL); }
417
418 else if(!strcmp (attribute_names[i], "minimum" )) { entry->minimum = g_ascii_strtod(attribute_values[i], NULL); }
419 else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); }
420 else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); }
421 else if(!strcmp (attribute_names[i], "notes" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->notes = g_strdup(attribute_values[i]); }
422 }
423
424 //all attribute loaded: append
425 da_acc_insert(entry);
426 }
427
428
429 static void homebank_load_xml_asg(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
430 {
431 Assign *entry = da_asg_malloc();
432 gint exact = 0;
433 gint i;
434
435 for (i = 0; attribute_names[i] != NULL; i++)
436 {
437 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
438
439 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
440 else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
441 else if(!strcmp (attribute_names[i], "field" )) { entry->field = atoi(attribute_values[i]); }
442 else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->text = g_strdup(attribute_values[i]); }
443 else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); }
444 else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); }
445 else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
446 // prior v08
447 else if(!strcmp (attribute_names[i], "exact" )) { exact = atoi(attribute_values[i]); }
448 }
449
450 /* in v08 exact moved to flag */
451 if( ctx->file_version <= 0.7)
452 {
453 entry->flags = (ASGF_DOCAT|ASGF_DOPAY);
454 if( exact > 0 )
455 entry->flags |= ASGF_EXACT;
456 }
457
458 //all attribute loaded: append
459 da_asg_append(entry);
460
461 }
462
463
464 static void homebank_load_xml_pay(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
465 {
466 Payee *entry = da_pay_malloc();
467 gint i;
468
469 for (i = 0; attribute_names[i] != NULL; i++)
470 {
471 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
472
473 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
474 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
475 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
476 else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); }
477 else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
478 }
479
480 //all attribute loaded: append
481 da_pay_insert(entry);
482 }
483
484
485 static void homebank_load_xml_prop(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
486 {
487 gint i;
488
489 for (i = 0; attribute_names[i] != NULL; i++)
490 {
491 if(!strcmp (attribute_names[i], "title" )) { g_free(GLOBALS->owner); GLOBALS->owner = g_strdup(attribute_values[i]); }
492 else if(!strcmp (attribute_names[i], "curr" )) { GLOBALS->kcur = atoi(attribute_values[i]); }
493 else if(!strcmp (attribute_names[i], "car_category")) { GLOBALS->vehicle_category = atoi(attribute_values[i]); }
494 else if(!strcmp (attribute_names[i], "auto_smode" )) { GLOBALS->auto_smode = atoi(attribute_values[i]); }
495 else if(!strcmp (attribute_names[i], "auto_weekday")) { GLOBALS->auto_weekday = atoi(attribute_values[i]); }
496 else if(!strcmp (attribute_names[i], "auto_nbdays" )) { GLOBALS->auto_nbdays = atoi(attribute_values[i]); }
497 }
498 }
499
500
501 static void homebank_load_xml_cat(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
502 {
503 Category *entry = da_cat_malloc();
504 gboolean budget;
505 gint i, j;
506
507 for (i = 0; attribute_names[i] != NULL; i++)
508 {
509 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
510
511 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
512 else if(!strcmp (attribute_names[i], "parent")) { entry->parent = atoi(attribute_values[i]); }
513 else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
514 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
515
516 budget = FALSE;
517 for(j=0;j<=12;j++)
518 {
519 gchar *tmpname;
520
521 tmpname = g_strdup_printf ("b%d", j);
522 if(!(strcmp (attribute_names[i], tmpname))) { entry->budget[j] = g_ascii_strtod(attribute_values[i], NULL); }
523 g_free(tmpname);
524
525 if(entry->budget[j]) budget = TRUE;
526 }
527 if(budget == TRUE)
528 entry->flags |= GF_BUDGET;
529
530 }
531
532 //all attribute loaded: append
533 da_cat_insert( entry);
534 }
535
536
537 static void homebank_load_xml_cur(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
538 {
539 Currency *entry = da_cur_malloc ();
540 gint i;
541
542 for (i = 0; attribute_names[i] != NULL; i++)
543 {
544 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
545
546 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
547 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
548 else if(!strcmp (attribute_names[i], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); }
549 else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[i]); }
550 else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); }
551 else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); }
552 else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); }
553 else if(!strcmp (attribute_names[i], "frac" )) { entry->frac_digits = atoi(attribute_values[i]); }
554 else if(!strcmp (attribute_names[i], "rate" )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); }
555 else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); }
556
557 }
558
559 //all attribute loaded: append
560 da_cur_insert (entry);
561 }
562
563
564 static void homebank_load_xml_tag(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
565 {
566 Tag *entry = da_tag_malloc();
567 gint i;
568
569 for (i = 0; attribute_names[i] != NULL; i++)
570 {
571 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
572
573 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
574 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
575 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
576 }
577
578 //all attribute loaded: append
579 da_tag_insert(entry);
580 }
581
582
583 static void homebank_load_xml_fav(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
584 {
585 Archive *entry = da_archive_malloc();
586 gchar *scat = NULL;
587 gchar *samt = NULL;
588 gchar *smem = NULL;
589 gboolean split = FALSE;
590 gint i;
591
592 for (i = 0; attribute_names[i] != NULL; i++)
593 {
594 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
595
596 if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
597 else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); }
598 else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
599 else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
600 else if(!strcmp (attribute_names[i], "st" )) { entry->status = atoi(attribute_values[i]); }
601 else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
602 else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); }
603 else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); }
604 else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
605 else if(!strcmp (attribute_names[i], "nextdate" )) { entry->nextdate = atoi(attribute_values[i]); }
606 else if(!strcmp (attribute_names[i], "every" )) { entry->every = atoi(attribute_values[i]); }
607 else if(!strcmp (attribute_names[i], "unit" )) { entry->unit = atoi(attribute_values[i]); }
608 else if(!strcmp (attribute_names[i], "limit" )) { entry->limit = atoi(attribute_values[i]); }
609 else if(!strcmp (attribute_names[i], "weekend" )) { entry->weekend = atoi(attribute_values[i]); }
610 else if(!strcmp (attribute_names[i], "scat" )) { scat = (gchar *)attribute_values[i]; split = TRUE; }
611 else if(!strcmp (attribute_names[i], "samt" )) { samt = (gchar *)attribute_values[i]; split = TRUE; }
612 else if(!strcmp (attribute_names[i], "smem" )) { smem = (gchar *)attribute_values[i]; split = TRUE; }
613
614 }
615
616 if(split == TRUE)
617 {
618 if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
619 {
620 entry->flags |= OF_SPLIT; //Flag that Splits are active
621 }
622 }
623
624 //all attribute loaded: append
625 GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry);
626 }
627
628
629 static void homebank_load_xml_ope(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
630 {
631 Transaction *entry = da_transaction_malloc();
632 gchar *scat = NULL;
633 gchar *samt = NULL;
634 gchar *smem = NULL;
635 gboolean split = FALSE;
636 gint i;
637
638 for (i = 0; attribute_names[i] != NULL; i++)
639 {
640 //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
641
642 if(!strcmp (attribute_names[i], "date" )) { entry->date = atoi(attribute_values[i]); }
643 else if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
644 else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); }
645 else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
646 else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
647 else if(!strcmp (attribute_names[i], "st" )) { entry->status = atoi(attribute_values[i]); }
648 else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
649 else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); }
650 else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); }
651 else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
652 else if(!strcmp (attribute_names[i], "info" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->info = g_strdup(attribute_values[i]); }
653 else if(!strcmp (attribute_names[i], "tags" ))
654 {
655 if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 )
656 {
657 transaction_tags_parse(entry, attribute_values[i]);
658 }
659 }
660 else if(!strcmp (attribute_names[i], "kxfer" )) { entry->kxfer = atoi(attribute_values[i]); }
661 else if(!strcmp (attribute_names[i], "scat" )) { scat = (gchar *)attribute_values[i]; split = TRUE; }
662 else if(!strcmp (attribute_names[i], "samt" )) { samt = (gchar *)attribute_values[i]; split = TRUE; }
663 else if(!strcmp (attribute_names[i], "smem" )) { smem = (gchar *)attribute_values[i]; split = TRUE; }
664 }
665
666 //bugfix 303886
667 //if(entry->kcat < 0)
668 // entry->kcat = 0;
669
670 if(split == TRUE)
671 {
672 if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
673 {
674 entry->flags |= OF_SPLIT; //Flag that Splits are active
675 }
676 }
677
678 //all attribute loaded: append
679 // we use prepend here, the list will be reversed later for perf reason
680 da_transaction_prepend(entry);
681 }
682
683
684
685
686 static void
687 start_element_handler (GMarkupParseContext *context,
688 const gchar *element_name,
689 const gchar **attribute_names,
690 const gchar **attribute_values,
691 gpointer user_data,
692 GError **error)
693 {
694 ParseContext *ctx = user_data;
695 //GtkUIManager *self = ctx->self;
696
697 //DB( g_print("** start element: %s\n", element_name) );
698
699 switch(element_name[0])
700 {
701 case 'a':
702 {
703 if(!strcmp (element_name, "account")) //account
704 {
705 homebank_load_xml_acc(ctx, attribute_names, attribute_values);
706 }
707 else if(!strcmp (element_name, "asg")) //assign
708 {
709 homebank_load_xml_asg(ctx, attribute_names, attribute_values);
710 }
711 }
712 break;
713
714 case 'p':
715 {
716 if(!strcmp (element_name, "pay"))
717 {
718 homebank_load_xml_pay(ctx, attribute_names, attribute_values);
719 }
720 else if(!strcmp (element_name, "properties"))
721 {
722 homebank_load_xml_prop(ctx, attribute_names, attribute_values);
723 }
724 }
725 break;
726
727 case 'c':
728 {
729 if(!strcmp (element_name, "cat"))
730 {
731 homebank_load_xml_cat(ctx, attribute_names, attribute_values);
732 }
733 else if(!strcmp (element_name, "cur"))
734 {
735 homebank_load_xml_cur(ctx, attribute_names, attribute_values);
736 }
737 }
738 break;
739
740 case 't':
741 {
742 if(!strcmp (element_name, "tags"))
743 {
744 homebank_load_xml_tag(ctx, attribute_names, attribute_values);
745 }
746 }
747
748 case 'f':
749 {
750 if(!strcmp (element_name, "fav"))
751 {
752 homebank_load_xml_fav(ctx, attribute_names, attribute_values);
753 }
754 }
755 break;
756
757 case 'o':
758 {
759 if(!strcmp (element_name, "ope"))
760 {
761 homebank_load_xml_ope(ctx, attribute_names, attribute_values);
762 }
763 }
764 break;
765 }
766 }
767
768
769 /*
770 static void
771 end_element_handler (GMarkupParseContext *context,
772 const gchar *element_name,
773 gpointer user_data,
774 GError **error)
775 {
776 ParseContext *ctx = user_data;
777
778 //DB( g_print("-- end element: %s\n", element_name) );
779
780
781 }
782 */
783
784 static GMarkupParser hb_parser = {
785 start_element_handler,
786 NULL, //end_element_handler,
787 NULL, //text_handler,
788 NULL,
789 NULL //cleanup
790 };
791
792
793 static gboolean hb_xml_get_version(ParseContext *ctx, gchar *buffer)
794 {
795 gchar *v_buffer;
796
797 ctx->file_version = 0.0;
798 ctx->data_version = 0;
799
800 /* v3.4 add :: prevent load of future file version */
801 v_buffer = g_strstr_len(buffer, 50, "<homebank v=");
802 if( v_buffer == NULL )
803 return FALSE;
804
805 DB( g_print("- id line: --(%.50s)\n\n", v_buffer) );
806
807 ctx->file_version = g_ascii_strtod(v_buffer+13, NULL); /* a little hacky, but works ! */
808 if( ctx->file_version == 0.0 )
809 ctx->file_version = 0.1;
810 else if( ctx->file_version == 5.0 ) //was a mistake
811 ctx->file_version = 1.0;
812
813 v_buffer = g_strstr_len(buffer+13, 50, "d=");
814 if( v_buffer )
815 {
816 DB( g_print(" d=%s)\n\n", v_buffer) );
817
818 ctx->data_version = atoi(v_buffer+3);
819 }
820 return TRUE;
821 }
822
823
824 /*
825 ** XML load homebank file: hbfile
826 */
827 gint homebank_load_xml(gchar *filename)
828 {
829 gint retval;
830 gchar *buffer;
831 gsize length;
832 GError *error = NULL;
833 ParseContext ctx;
834 GMarkupParseContext *context;
835 gboolean rc;
836
837 DB( g_print("\n[hb-xml] homebank_load_xml\n") );
838
839 retval = XML_OK;
840 if (!g_file_get_contents (filename, &buffer, &length, &error))
841 {
842 //g_message ("%s", error->message);
843 retval = XML_IO_ERROR;
844 g_error_free (error);
845 }
846 else
847 {
848 if( hb_xml_get_version(&ctx, buffer) == FALSE )
849 {
850 return XML_FILE_ERROR;
851 }
852
853 if( ctx.file_version > FILE_VERSION )
854 {
855 DB( g_print("- failed: version %f is not supported (max is %f)\n", ctx.file_version, FILE_VERSION) );
856 return XML_VERSION_ERROR;
857 }
858 else
859 {
860 DB( g_print("- file ok : v=%.1f data_v=%06d\n", ctx.file_version, ctx.data_version) );
861
862 /* 1st: validate the file is well in utf-8 */
863 DB( g_print("- ensure UTF-8\n") );
864 buffer = homebank_utf8_ensure(buffer);
865
866 /* then process the buffer */
867 #if MYDEBUG == 1
868 GTimer *t = g_timer_new();
869 g_print("- start parse\n");
870 #endif
871
872 context = g_markup_parse_context_new (&hb_parser, 0, &ctx, NULL);
873
874 error = NULL;
875 rc = g_markup_parse_context_parse (context, buffer, length, &error);
876
877 if( error )
878 g_print("failed: %s\n", error->message);
879
880 if( rc == FALSE )
881 {
882 error = NULL;
883 g_markup_parse_context_end_parse(context, &error);
884
885 if( error )
886 g_print("failed: %s\n", error->message);
887 }
888
889 g_markup_parse_context_free (context);
890 g_free (buffer);
891
892 DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t, NULL)) );
893 DB( g_timer_destroy (t) );
894
895 /* file upgrade / bugfix */
896 if( ctx.file_version <= 0.1 )
897 homebank_upgrade_to_v02();
898 if( ctx.file_version <= 0.2 )
899 homebank_upgrade_to_v03();
900 if( ctx.file_version <= 0.3 )
901 homebank_upgrade_to_v04();
902 if( ctx.file_version <= 0.4 )
903 homebank_upgrade_to_v05();
904 if( ctx.file_version <= 0.5 )
905 {
906 homebank_upgrade_to_v06();
907 homebank_upgrade_lower_v06();
908 }
909 if( ctx.file_version <= 0.6 )
910 {
911 homebank_upgrade_to_v07();
912 hbfile_sanity_check();
913 }
914 if( ctx.file_version <= 0.7 ) // <= 4.5
915 {
916 homebank_upgrade_to_v08();
917 }
918 if( ctx.file_version <= 0.8 ) // <= 4.6
919 {
920 hbfile_sanity_check();
921 }
922 if( ctx.file_version <= 0.9 ) // <= 4.6.3
923 {
924 hbfile_sanity_check();
925 homebank_upgrade_to_v10();
926 }
927 if( ctx.file_version <= 1.0 ) // <= 5.0.0
928 {
929 hbfile_sanity_check();
930 homebank_upgrade_to_v11();
931 }
932 //starting 5.0.4 data upgrade is done without changing file_version
933 if( ctx.data_version < 050005 ) // <= 5.0.5
934 {
935 hbfile_sanity_check();
936 }
937 if( ctx.file_version <= 1.1 ) // <= 5.1.0
938 {
939 hbfile_sanity_check();
940 homebank_upgrade_to_v12();
941 }
942
943 // next ?
944
945 }
946 }
947
948 return retval;
949 }
950
951
952
953 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
954
955 /*
956 ** misc xml attributes methods
957 */
958 static void hb_xml_append_txt(GString *gstring, gchar *attrname, gchar *value)
959 {
960 if(value != NULL && *value != 0)
961 {
962 gchar *escaped = g_markup_escape_text(value, -1);
963 g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped);
964 g_free(escaped);
965 }
966 }
967
968 static void
969 append_escaped_text (GString *str,
970 const gchar *text,
971 gssize length)
972 {
973 const gchar *p;
974 const gchar *end;
975 gunichar c;
976
977 p = text;
978 end = text + length;
979
980 while (p < end)
981 {
982 const gchar *next;
983 next = g_utf8_next_char (p);
984
985 switch (*p)
986 {
987 case '&':
988 g_string_append (str, "&amp;");
989 break;
990
991 case '<':
992 g_string_append (str, "&lt;");
993 break;
994
995 case '>':
996 g_string_append (str, "&gt;");
997 break;
998
999 case '\'':
1000 g_string_append (str, "&apos;");
1001 break;
1002
1003 case '"':
1004 g_string_append (str, "&quot;");
1005 break;
1006
1007 default:
1008 c = g_utf8_get_char (p);
1009 if ((0x1 <= c && c <= 0x8) ||
1010 (0xa <= c && c <= 0xd) || //chnaged here from b<->c to a<->d
1011 (0xe <= c && c <= 0x1f) ||
1012 (0x7f <= c && c <= 0x84) ||
1013 (0x86 <= c && c <= 0x9f))
1014 g_string_append_printf (str, "&#x%x;", c);
1015 else
1016 g_string_append_len (str, p, next - p);
1017 break;
1018 }
1019
1020 p = next;
1021 }
1022 }
1023
1024 // we override g_markup_escape_text from glib to encode \n (LF) & \r (CR)
1025 static void hb_xml_append_txt_crlf(GString *gstring, gchar *attrname, gchar *value)
1026 {
1027 if(value != NULL && *value != 0)
1028 {
1029 gssize length;
1030 GString *escaped;
1031
1032 //gchar *escaped = g_markup_escape_text(value, -1);
1033 length = strlen (value);
1034 escaped = g_string_sized_new (length);
1035 append_escaped_text (escaped, value, length);
1036 g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped->str);
1037 g_string_free (escaped, TRUE);
1038 }
1039 }
1040
1041 static void hb_xml_append_int0(GString *gstring, gchar *attrname, guint32 value)
1042 {
1043 g_string_append_printf(gstring, "%s=\"%d\" ", attrname, value);
1044 }
1045
1046 static void hb_xml_append_int(GString *gstring, gchar *attrname, guint32 value)
1047 {
1048 if(value != 0)
1049 {
1050 hb_xml_append_int0(gstring, attrname, value);
1051 }
1052 }
1053
1054 static void hb_xml_append_amt(GString *gstring, gchar *attrname, gdouble amount)
1055 {
1056 char buf[G_ASCII_DTOSTR_BUF_SIZE];
1057
1058 //we must use this, as fprintf use locale decimal settings and not '.'
1059 g_ascii_dtostr (buf, sizeof (buf), amount);
1060 g_string_append_printf(gstring, "%s=\"%s\" ", attrname, buf);
1061 }
1062
1063
1064 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1065
1066
1067 /*
1068 ** XML properties save
1069 */
1070 static gint homebank_save_xml_prop(GIOChannel *io)
1071 {
1072 gchar *title;
1073 GString *node;
1074 gint retval = XML_OK;
1075 GError *error = NULL;
1076
1077 title = GLOBALS->owner == NULL ? "" : GLOBALS->owner;
1078
1079 node = g_string_sized_new(255);
1080
1081 g_string_assign(node, "<properties ");
1082
1083 hb_xml_append_txt(node, "title", title);
1084 hb_xml_append_int(node, "curr", GLOBALS->kcur);
1085 hb_xml_append_int(node, "car_category", GLOBALS->vehicle_category);
1086 hb_xml_append_int0(node, "auto_smode", GLOBALS->auto_smode);
1087 hb_xml_append_int(node, "auto_weekday", GLOBALS->auto_weekday);
1088 hb_xml_append_int(node, "auto_nbdays", GLOBALS->auto_nbdays);
1089
1090 g_string_append(node, "/>\n");
1091
1092 error = NULL;
1093 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1094 if(error)
1095 {
1096 retval = XML_IO_ERROR;
1097 g_error_free(error);
1098 }
1099
1100 g_string_free(node, TRUE);
1101 return retval;
1102 }
1103
1104
1105 /*
1106 ** XML currency save
1107 */
1108 static gint homebank_save_xml_cur(GIOChannel *io)
1109 {
1110 GList *list;
1111 gchar *tmpstr;
1112 char buf1[G_ASCII_DTOSTR_BUF_SIZE];
1113 gint retval = XML_OK;
1114
1115 list = g_hash_table_get_values(GLOBALS->h_cur);
1116 while (list != NULL)
1117 {
1118 Currency *item = list->data;
1119
1120 tmpstr = g_markup_printf_escaped(
1121 "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
1122 item->key,
1123 item->iso_code,
1124 item->name,
1125 item->symbol,
1126 item->sym_prefix,
1127 item->decimal_char,
1128 item->grouping_char,
1129 item->frac_digits,
1130 g_ascii_dtostr (buf1, sizeof (buf1), item->rate),
1131 item->mdate
1132 );
1133
1134 g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
1135 g_free(tmpstr);
1136
1137 list = g_list_next(list);
1138 }
1139 g_list_free(list);
1140 return retval;
1141 }
1142
1143
1144 /*
1145 ** XML account save
1146 */
1147 static gint homebank_save_xml_acc(GIOChannel *io)
1148 {
1149 GList *lacc, *list;
1150 GString *node;
1151 gint retval = XML_OK;
1152 GError *error = NULL;
1153
1154 node = g_string_sized_new(255);
1155
1156 lacc = list = account_glist_sorted(0);
1157 while (list != NULL)
1158 {
1159 Account *item = list->data;
1160
1161 item->flags &= ~(AF_ADDED|AF_CHANGED); //delete flag
1162
1163 g_string_assign(node, "<account ");
1164
1165 hb_xml_append_int(node, "key", item->key);
1166 hb_xml_append_int(node, "flags", item->flags);
1167 hb_xml_append_int(node, "pos", item->pos);
1168 hb_xml_append_int(node, "type", item->type);
1169 hb_xml_append_int(node, "curr", item->kcur);
1170 hb_xml_append_txt(node, "name", item->name);
1171 hb_xml_append_txt(node, "number", item->number);
1172 hb_xml_append_txt(node, "bankname", item->bankname);
1173 hb_xml_append_amt(node, "initial", item->initial);
1174
1175 hb_xml_append_amt(node, "minimum", item->minimum);
1176 hb_xml_append_int(node, "cheque1", item->cheque1);
1177 hb_xml_append_int(node, "cheque2", item->cheque2);
1178 hb_xml_append_txt_crlf(node, "notes", item->notes);
1179
1180 g_string_append(node, "/>\n");
1181
1182 error = NULL;
1183 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1184
1185 if(error)
1186 {
1187 retval = XML_IO_ERROR;
1188 g_error_free(error);
1189 }
1190
1191 list = g_list_next(list);
1192 }
1193 g_list_free(lacc);
1194 g_string_free(node, TRUE);
1195 return retval;
1196 }
1197
1198 /*
1199 ** XML payee save
1200 */
1201 static gint homebank_save_xml_pay(GIOChannel *io)
1202 {
1203 GList *lpay, *list;
1204 GString *node;
1205 gint retval = XML_OK;
1206 GError *error = NULL;
1207
1208 node = g_string_sized_new(255);
1209
1210 lpay = list = payee_glist_sorted(0);
1211 while (list != NULL)
1212 {
1213 Payee *item = list->data;
1214
1215 if(item->key != 0)
1216 {
1217 g_string_assign(node, "<pay ");
1218
1219 hb_xml_append_int(node, "key", item->key);
1220 hb_xml_append_txt(node, "name", item->name);
1221 hb_xml_append_int(node, "category", item->kcat);
1222 hb_xml_append_int(node, "paymode" , item->paymode);
1223
1224 g_string_append(node, "/>\n");
1225
1226 error = NULL;
1227 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1228
1229 if(error)
1230 {
1231 retval = XML_IO_ERROR;
1232 g_error_free(error);
1233 }
1234
1235 }
1236 list = g_list_next(list);
1237 }
1238 g_list_free(lpay);
1239 g_string_free(node, TRUE);
1240 return retval;
1241 }
1242
1243 /*
1244 ** XML category save
1245 */
1246 static gint homebank_save_xml_cat(GIOChannel *io)
1247 {
1248 GList *lcat, *list;
1249 GString *node;
1250 char buf[G_ASCII_DTOSTR_BUF_SIZE];
1251 guint i;
1252 gint retval = XML_OK;
1253 GError *error = NULL;
1254
1255 node = g_string_sized_new(255);
1256
1257 lcat = list = category_glist_sorted(0);
1258 while (list != NULL)
1259 {
1260 Category *item = list->data;
1261
1262 if(item->key != 0)
1263 {
1264 g_string_assign(node, "<cat ");
1265
1266 hb_xml_append_int(node, "key", item->key);
1267 hb_xml_append_int(node, "parent", item->parent);
1268 hb_xml_append_int(node, "flags", item->flags);
1269 hb_xml_append_txt(node, "name", item->name);
1270
1271 for(i=0;i<=12;i++)
1272 {
1273 if(item->budget[i] != 0)
1274 {
1275 g_string_append_printf(node,"b%d=\"%s\" ", i, g_ascii_dtostr (buf, sizeof (buf), item->budget[i]));
1276 }
1277 }
1278
1279 g_string_append(node, "/>\n");
1280
1281 error = NULL;
1282 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1283
1284 if(error)
1285 {
1286 retval = XML_IO_ERROR;
1287 g_error_free(error);
1288 }
1289
1290 }
1291 list = g_list_next(list);
1292 }
1293 g_list_free(lcat);
1294 g_string_free(node, TRUE);
1295 return retval;
1296 }
1297
1298 /*
1299 ** XML tag save
1300 */
1301 static gint homebank_save_xml_tag(GIOChannel *io)
1302 {
1303 GList *ltag, *list;
1304 gchar *tmpstr;
1305 gint retval = XML_OK;
1306 GError *error = NULL;
1307
1308 ltag = list = tag_glist_sorted(0);
1309 while (list != NULL)
1310 {
1311 Tag *item = list->data;
1312
1313 if(item->key != 0)
1314 {
1315 tmpstr = g_markup_printf_escaped("<tag key=\"%d\" name=\"%s\"/>\n",
1316 item->key,
1317 item->name
1318 );
1319
1320 error = NULL;
1321 g_io_channel_write_chars(io, tmpstr, -1, NULL, &error);
1322 g_free(tmpstr);
1323
1324 if(error)
1325 {
1326 retval = XML_IO_ERROR;
1327 g_error_free(error);
1328 }
1329 }
1330 list = g_list_next(list);
1331 }
1332 g_list_free(ltag);
1333 return retval;
1334 }
1335
1336
1337 /*
1338 ** XML assign save
1339 */
1340 static gint homebank_save_xml_asg(GIOChannel *io)
1341 {
1342 GList *lasg, *list;
1343 GString *node;
1344 gint retval = XML_OK;
1345 GError *error = NULL;
1346
1347 node = g_string_sized_new(255);
1348
1349 lasg = list = assign_glist_sorted(0);
1350 while (list != NULL)
1351 {
1352 Assign *item = list->data;
1353
1354 g_string_assign(node, "<asg ");
1355
1356 hb_xml_append_int(node, "key" , item->key);
1357 hb_xml_append_int(node, "flags" , item->flags);
1358 hb_xml_append_int(node, "field" , item->field);
1359 hb_xml_append_txt(node, "name" , item->text);
1360 hb_xml_append_int(node, "payee" , item->kpay);
1361 hb_xml_append_int(node, "category", item->kcat);
1362 hb_xml_append_int(node, "paymode" , item->paymode);
1363
1364 g_string_append(node, "/>\n");
1365
1366 error = NULL;
1367 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1368
1369 if(error)
1370 {
1371 retval = XML_IO_ERROR;
1372 g_error_free(error);
1373 }
1374
1375 list = g_list_next(list);
1376 }
1377 g_list_free(lasg);
1378 g_string_free(node, TRUE);
1379 return retval;
1380 }
1381
1382
1383
1384 /*
1385 ** XML archive save
1386 */
1387 static gint homebank_save_xml_arc(GIOChannel *io)
1388 {
1389 GList *list;
1390 GString *node;
1391 gint retval = XML_OK;
1392 GError *error = NULL;
1393
1394 node = g_string_sized_new(255);
1395
1396 list = g_list_first(GLOBALS->arc_list);
1397 while (list != NULL)
1398 {
1399 Archive *item = list->data;
1400
1401 g_string_assign(node, "<fav ");
1402
1403 hb_xml_append_amt(node, "amount", item->amount);
1404 hb_xml_append_int(node, "account", item->kacc);
1405 hb_xml_append_int(node, "dst_account", item->kxferacc);
1406 hb_xml_append_int(node, "paymode", item->paymode);
1407 hb_xml_append_int(node, "st", item->status);
1408 hb_xml_append_int(node, "flags", item->flags);
1409 hb_xml_append_int(node, "payee", item->kpay);
1410 hb_xml_append_int(node, "category", item->kcat);
1411 hb_xml_append_txt(node, "wording", item->wording);
1412 hb_xml_append_int(node, "nextdate", item->nextdate);
1413 hb_xml_append_int(node, "every", item->every);
1414 hb_xml_append_int(node, "unit", item->unit);
1415 hb_xml_append_int(node, "limit", item->limit);
1416 hb_xml_append_int(node, "weekend", item->weekend);
1417
1418 if(da_splits_count(item->splits) > 0)
1419 {
1420 gchar *cats, *amounts, *memos;
1421
1422 da_splits_tostring(item->splits, &cats, &amounts, &memos);
1423 g_string_append_printf(node, "scat=\"%s\" ", cats);
1424 g_string_append_printf(node, "samt=\"%s\" ", amounts);
1425
1426 //fix #1173910
1427 gchar *escaped = g_markup_escape_text(memos, -1);
1428 g_string_append_printf(node, "smem=\"%s\" ", escaped);
1429 g_free(escaped);
1430
1431 g_free(cats);
1432 g_free(amounts);
1433 g_free(memos);
1434 }
1435
1436 g_string_append(node, "/>\n");
1437
1438 error = NULL;
1439 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1440 if(error)
1441 {
1442 retval = XML_IO_ERROR;
1443 g_error_free(error);
1444 }
1445
1446 list = g_list_next(list);
1447 }
1448 g_string_free(node, TRUE);
1449 return retval;
1450 }
1451
1452
1453 /*
1454 ** XML transaction save
1455 */
1456 static gint homebank_save_xml_ope(GIOChannel *io)
1457 {
1458 GList *lst_acc, *lnk_acc;
1459 GList *list;
1460 GString *node;
1461 gchar *tagstr;
1462 gint retval = XML_OK;
1463 GError *error = NULL;
1464
1465 node = g_string_sized_new(255);
1466
1467 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
1468 lnk_acc = g_list_first(lst_acc);
1469 while (lnk_acc != NULL)
1470 {
1471 Account *acc = lnk_acc->data;
1472
1473 list = g_queue_peek_head_link(acc->txn_queue);
1474 while (list != NULL)
1475 {
1476 Transaction *item = list->data;
1477
1478 item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED); //delete flag
1479 tagstr = transaction_tags_tostring(item);
1480
1481 g_string_assign(node, "<ope ");
1482
1483 hb_xml_append_int(node, "date", item->date);
1484 hb_xml_append_amt(node, "amount", item->amount);
1485 hb_xml_append_int(node, "account", item->kacc);
1486 hb_xml_append_int(node, "dst_account", item->kxferacc);
1487 hb_xml_append_int(node, "paymode", item->paymode);
1488 hb_xml_append_int(node, "st", item->status);
1489 hb_xml_append_int(node, "flags", item->flags);
1490 hb_xml_append_int(node, "payee", item->kpay);
1491 hb_xml_append_int(node, "category", item->kcat);
1492 hb_xml_append_txt(node, "wording", item->wording);
1493 hb_xml_append_txt(node, "info", item->info);
1494 hb_xml_append_txt(node, "tags", tagstr);
1495 hb_xml_append_int(node, "kxfer", item->kxfer);
1496
1497 if(da_splits_count(item->splits) > 0)
1498 {
1499 gchar *cats, *amounts, *memos;
1500
1501 da_splits_tostring(item->splits, &cats, &amounts, &memos);
1502 g_string_append_printf(node, "scat=\"%s\" ", cats);
1503 g_string_append_printf(node, "samt=\"%s\" ", amounts);
1504
1505 //fix #1173910
1506 gchar *escaped = g_markup_escape_text(memos, -1);
1507 g_string_append_printf(node, "smem=\"%s\" ", escaped);
1508 g_free(escaped);
1509
1510 g_free(cats);
1511 g_free(amounts);
1512 g_free(memos);
1513 }
1514
1515 g_string_append(node, "/>\n");
1516
1517 g_free(tagstr);
1518
1519 error = NULL;
1520 g_io_channel_write_chars(io, node->str, -1, NULL, &error);
1521
1522 if(error)
1523 {
1524 retval = XML_IO_ERROR;
1525 g_error_free(error);
1526 }
1527
1528 list = g_list_next(list);
1529 }
1530
1531 lnk_acc = g_list_next(lnk_acc);
1532 }
1533 g_list_free(lst_acc);
1534
1535 g_string_free(node, TRUE);
1536 return retval;
1537 }
1538
1539 /*
1540 ** XML save homebank file: hbfile
1541 */
1542 gint homebank_save_xml(gchar *filename)
1543 {
1544 GIOChannel *io;
1545 char buf1[G_ASCII_DTOSTR_BUF_SIZE];
1546 gchar *outstr;
1547 gint retval = XML_OK;
1548 GError *error = NULL;
1549
1550 io = g_io_channel_new_file(filename, "w", &error);
1551 if(io == NULL)
1552 {
1553 g_message("file error on: %s", filename);
1554 retval = XML_IO_ERROR;
1555
1556 if(error)
1557 g_print("failed: %s\n", error->message);
1558
1559 g_error_free(error);
1560 }
1561 else
1562 {
1563 g_io_channel_write_chars(io, "<?xml version=\"1.0\"?>\n", -1, NULL, NULL);
1564
1565 outstr = g_strdup_printf("<homebank v=\"%s\" d=\"%06d\">\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION), HB_VERSION_NUM);
1566 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
1567 g_free(outstr);
1568
1569 retval = homebank_save_xml_prop(io);
1570 retval = homebank_save_xml_cur(io);
1571 retval = homebank_save_xml_acc(io);
1572 retval = homebank_save_xml_pay(io);
1573 retval = homebank_save_xml_cat(io);
1574 retval = homebank_save_xml_tag(io);
1575 retval = homebank_save_xml_asg(io);
1576 retval = homebank_save_xml_arc(io);
1577 retval = homebank_save_xml_ope(io);
1578
1579 g_io_channel_write_chars(io, "</homebank>\n", -1, NULL, NULL);
1580
1581 g_io_channel_unref (io);
1582 }
1583 return retval;
1584 }
1585
This page took 0.113207 seconds and 4 git commands to generate.