1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 Maxime DOYEN
4 * This file is part of HomeBank.
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.
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.
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/>.
23 #include "hb-transaction.h"
26 /****************************************************************************/
28 /****************************************************************************/
37 /* our global datas */
38 extern struct HomeBank
*GLOBALS
;
39 extern struct Preferences
*PREFS
;
41 typedef struct _ParseContext ParseContext
;
48 static void homebank_upgrade_to_v02(void);
49 static void homebank_upgrade_to_v03(void);
50 static void homebank_upgrade_to_v04(void);
51 static void homebank_upgrade_to_v05(void);
52 static void homebank_upgrade_lower_v06(void);
53 static void homebank_upgrade_to_v06(void);
54 static void homebank_upgrade_to_v07(void);
55 static void homebank_upgrade_to_v08(void);
58 start_element_handler (GMarkupParseContext
*context
,
59 const gchar
*element_name
,
60 const gchar
**attribute_names
,
61 const gchar
**attribute_values
,
65 ParseContext
*ctx
= user_data
;
66 //GtkUIManager *self = ctx->self;
69 //DB( g_print("** start element: %s\n", element_name) );
71 switch(element_name
[0])
77 if(!strcmp (element_name, "homebank"))
79 if(!strcmp (attribute_names[0], "v" ))
81 version = g_ascii_strtod(attribute_values[0], NULL);
82 DB( g_print(" version %f\n", version) );
91 if(!strcmp (element_name
, "account"))
93 Account
*entry
= da_acc_malloc();
95 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
97 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
99 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
100 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
101 else if(!strcmp (attribute_names
[i
], "pos" )) { entry
->pos
= atoi(attribute_values
[i
]); }
102 else if(!strcmp (attribute_names
[i
], "type" )) { entry
->type
= atoi(attribute_values
[i
]); }
103 //else if(!strcmp (attribute_names[i], "curr" )) { entry->kcur = atoi(attribute_values[i]); }
104 else if(!strcmp (attribute_names
[i
], "name" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->name
= g_strdup(attribute_values
[i
]); }
105 else if(!strcmp (attribute_names
[i
], "number" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->number
= g_strdup(attribute_values
[i
]); }
106 else if(!strcmp (attribute_names
[i
], "bankname")) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->bankname
= g_strdup(attribute_values
[i
]); }
107 else if(!strcmp (attribute_names
[i
], "initial" )) { entry
->initial
= g_ascii_strtod(attribute_values
[i
], NULL
); }
108 else if(!strcmp (attribute_names
[i
], "minimum" )) { entry
->minimum
= g_ascii_strtod(attribute_values
[i
], NULL
); }
109 else if(!strcmp (attribute_names
[i
], "cheque1" )) { entry
->cheque1
= atoi(attribute_values
[i
]); }
110 else if(!strcmp (attribute_names
[i
], "cheque2" )) { entry
->cheque2
= atoi(attribute_values
[i
]); }
114 //version upgrade: type was added in 0.2
115 //todo: for stock account
119 entry->type = ACC_TYPE_BANK;
120 DB( g_print(" acctype forced to BANK\n") );
124 DB( g_print(" version %f\n", ctx
->version
) );
126 //upgrade to v0.2 file
127 // we must change account reference by making a +1 to its index references
128 if( ctx
->version
== 0.1 )
131 entry
->pos
= entry
->key
;
134 //all attribute loaded: append
135 da_acc_insert(entry
);
139 else if(!strcmp (element_name
, "asg"))
141 Assign
*entry
= da_asg_malloc();
144 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
146 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
148 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
149 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
150 else if(!strcmp (attribute_names
[i
], "field" )) { entry
->field
= atoi(attribute_values
[i
]); }
151 else if(!strcmp (attribute_names
[i
], "name" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->name
= g_strdup(attribute_values
[i
]); }
152 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
153 else if(!strcmp (attribute_names
[i
], "category")) { entry
->kcat
= atoi(attribute_values
[i
]); }
154 //else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
156 else if(!strcmp (attribute_names
[i
], "exact" )) { exact
= atoi(attribute_values
[i
]); }
159 /* in v08 exact moved to flag */
160 if( ctx
->version
<= 0.7)
162 entry
->flags
= (ASGF_DOCAT
|ASGF_DOPAY
);
164 entry
->flags
|= ASGF_EXACT
;
167 //all attribute loaded: append
168 da_asg_append(entry
);
177 if(!strcmp (element_name
, "pay"))
179 Payee
*entry
= da_pay_malloc();
181 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
183 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
185 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
186 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
187 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
190 //all attribute loaded: append
191 da_pay_insert(entry
);
194 else if(!strcmp (element_name
, "properties"))
196 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
198 if(!strcmp (attribute_names
[i
], "title" )) { g_free(GLOBALS
->owner
); GLOBALS
->owner
= g_strdup(attribute_values
[i
]); }
199 //else if(!strcmp (attribute_names[i], "curr" )) { GLOBALS->kcur = atoi(attribute_values[i]); }
200 else if(!strcmp (attribute_names
[i
], "car_category")) { GLOBALS
->vehicle_category
= atoi(attribute_values
[i
]); }
201 else if(!strcmp (attribute_names
[i
], "auto_smode" )) { GLOBALS
->auto_smode
= atoi(attribute_values
[i
]); }
202 else if(!strcmp (attribute_names
[i
], "auto_weekday")) { GLOBALS
->auto_weekday
= atoi(attribute_values
[i
]); }
203 else if(!strcmp (attribute_names
[i
], "auto_nbdays" )) { GLOBALS
->auto_nbdays
= atoi(attribute_values
[i
]); }
211 if(!strcmp (element_name
, "cat"))
213 Category
*entry
= da_cat_malloc();
216 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
218 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
220 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
221 else if(!strcmp (attribute_names
[i
], "parent")) { entry
->parent
= atoi(attribute_values
[i
]); }
222 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
223 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
230 tmpname
= g_strdup_printf ("b%d", j
);
231 if(!(strcmp (attribute_names
[i
], tmpname
))) { entry
->budget
[j
] = g_ascii_strtod(attribute_values
[i
], NULL
); }
234 if(entry
->budget
[j
]) budget
= TRUE
;
237 entry
->flags
|= GF_BUDGET
;
241 //all attribute loaded: append
242 da_cat_insert( entry
);
244 /* else if(!strcmp (element_name, "cur"))
246 Currency *entry = da_cur_malloc ();
248 for (i = 0; attribute_names[i] != NULL; i++)
250 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
252 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
253 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
254 else if(!strcmp (attribute_names[i], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); }
255 else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[i]); }
256 else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); }
257 else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); }
258 else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); }
259 else if(!strcmp (attribute_names[i], "frac" )) { entry->frac_digits = atoi(attribute_values[i]); }
260 else if(!strcmp (attribute_names[i], "rate" )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); }
261 else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); }
265 //all attribute loaded: append
266 da_cur_insert (entry);
274 if(!strcmp (element_name
, "tags"))
276 Tag
*entry
= da_tag_malloc();
278 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
280 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
282 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
283 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
284 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
287 //all attribute loaded: append
288 da_tag_insert(entry
);
295 if(!strcmp (element_name
, "fav"))
297 Archive
*entry
= da_archive_malloc();
299 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
301 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
303 if(!strcmp (attribute_names
[i
], "amount" )) { entry
->amount
= g_ascii_strtod(attribute_values
[i
], NULL
); }
304 else if(!strcmp (attribute_names
[i
], "account" )) { entry
->kacc
= atoi(attribute_values
[i
]); }
305 else if(!strcmp (attribute_names
[i
], "dst_account")) { entry
->kxferacc
= atoi(attribute_values
[i
]); }
306 else if(!strcmp (attribute_names
[i
], "paymode" )) { entry
->paymode
= atoi(attribute_values
[i
]); }
307 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
308 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
309 else if(!strcmp (attribute_names
[i
], "category" )) { entry
->kcat
= atoi(attribute_values
[i
]); }
310 else if(!strcmp (attribute_names
[i
], "wording" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->wording
= g_strdup(attribute_values
[i
]); }
311 else if(!strcmp (attribute_names
[i
], "nextdate" )) { entry
->nextdate
= atoi(attribute_values
[i
]); }
312 else if(!strcmp (attribute_names
[i
], "every" )) { entry
->every
= atoi(attribute_values
[i
]); }
313 else if(!strcmp (attribute_names
[i
], "unit" )) { entry
->unit
= atoi(attribute_values
[i
]); }
314 else if(!strcmp (attribute_names
[i
], "limit" )) { entry
->limit
= atoi(attribute_values
[i
]); }
315 else if(!strcmp (attribute_names
[i
], "weekend" )) { entry
->weekend
= atoi(attribute_values
[i
]); }
319 //all attribute loaded: append
320 GLOBALS
->arc_list
= g_list_append(GLOBALS
->arc_list
, entry
);
335 if(!strcmp (element_name
, "ope"))
337 Transaction
*entry
= da_transaction_malloc();
341 gboolean split
= FALSE
;
343 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
345 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
347 if(!strcmp (attribute_names
[i
], "date" )) { entry
->date
= atoi(attribute_values
[i
]); }
348 else if(!strcmp (attribute_names
[i
], "amount" )) { entry
->amount
= g_ascii_strtod(attribute_values
[i
], NULL
); }
349 else if(!strcmp (attribute_names
[i
], "account" )) { entry
->kacc
= atoi(attribute_values
[i
]); }
350 else if(!strcmp (attribute_names
[i
], "dst_account")) { entry
->kxferacc
= atoi(attribute_values
[i
]); }
351 else if(!strcmp (attribute_names
[i
], "paymode" )) { entry
->paymode
= atoi(attribute_values
[i
]); }
352 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
353 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
354 else if(!strcmp (attribute_names
[i
], "category" )) { entry
->kcat
= atoi(attribute_values
[i
]); }
355 else if(!strcmp (attribute_names
[i
], "wording" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->wording
= g_strdup(attribute_values
[i
]); }
356 else if(!strcmp (attribute_names
[i
], "info" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->info
= g_strdup(attribute_values
[i
]); }
357 else if(!strcmp (attribute_names
[i
], "tags" ))
359 if(attribute_values
[i
] != NULL
&& strlen(attribute_values
[i
]) > 0 && strcmp(attribute_values
[i
],"(null)") != 0 )
361 transaction_tags_parse(entry
, attribute_values
[i
]);
364 else if(!strcmp (attribute_names
[i
], "kxfer" )) { entry
->kxfer
= atoi(attribute_values
[i
]); }
365 else if(!strcmp (attribute_names
[i
], "scat" )) { scat
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
366 else if(!strcmp (attribute_names
[i
], "samt" )) { samt
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
367 else if(!strcmp (attribute_names
[i
], "smem" )) { smem
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
371 //if(entry->kcat < 0)
376 transaction_splits_parse(entry
, scat
, samt
, smem
);
379 //all attribute loaded: append
380 // we use prepend here, the list will be reversed later for perf reason
381 da_transaction_prepend(entry
);
394 end_element_handler (GMarkupParseContext *context,
395 const gchar *element_name,
399 ParseContext *ctx = user_data;
401 //DB( g_print("-- end element: %s\n", element_name) );
407 static GMarkupParser hb_parser
= {
408 start_element_handler
,
409 NULL
, //end_element_handler,
410 NULL
, //text_handler,
416 ** XML load homebank file: hbfile
418 gint
homebank_load_xml(gchar
*filename
)
423 GError
*error
= NULL
;
424 ParseContext ctx
= { 0 };
425 GMarkupParseContext
*context
;
428 DB( g_print("\n[hb-xml] homebank_load_xml\n") );
431 if (!g_file_get_contents (filename
, &buffer
, &length
, &error
))
433 //g_message ("%s", error->message);
434 retval
= XML_IO_ERROR
;
435 g_error_free (error
);
442 /* v3.4 add :: prevent load of future file version */
443 v_buffer
= g_strstr_len(buffer
, 50, "<homebank v=");
444 if( v_buffer
== NULL
)
445 return XML_FILE_ERROR
;
447 DB( g_print("- id line: --(%.50s)\n\n", v_buffer
) );
449 version
= g_ascii_strtod(v_buffer
+13, NULL
); /* a little hacky, but works ! */
453 ctx
.version
= version
;
455 if( version
> FILE_VERSION
)
457 DB( g_print("- failed: version %f is not supported (max is %f)\n", version
, FILE_VERSION
) );
458 return XML_VERSION_ERROR
;
462 DB( g_print("- ok : version=%.1f\n", version
) );
464 /* 1st: validate the file is well in utf-8 */
465 DB( g_print("- ensure UTF-8\n") );
466 buffer
= homebank_utf8_ensure(buffer
);
468 /* then process the buffer */
470 GTimer
*t
= g_timer_new();
471 g_print("- start parse\n");
474 context
= g_markup_parse_context_new (&hb_parser
, 0, &ctx
, NULL
);
477 rc
= g_markup_parse_context_parse (context
, buffer
, length
, &error
);
480 g_print("failed: %s\n", error
->message
);
485 g_markup_parse_context_end_parse(context
, &error
);
488 g_print("failed: %s\n", error
->message
);
491 g_markup_parse_context_free (context
);
494 //reverse the glist (see g_list append idiom to perf for reason
495 // we use prepend and then reverse
496 GLOBALS
->ope_list
= g_list_reverse(GLOBALS
->ope_list
);
498 DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t
, NULL
)) );
499 DB( g_timer_destroy (t
) );
501 /* file upgrade / bugfix */
503 homebank_upgrade_to_v02();
505 homebank_upgrade_to_v03();
507 homebank_upgrade_to_v04();
509 homebank_upgrade_to_v05();
512 homebank_upgrade_to_v06();
513 homebank_upgrade_lower_v06();
517 homebank_upgrade_to_v07();
518 hbfile_sanity_check();
521 homebank_upgrade_to_v08();
523 hbfile_sanity_check();
534 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
536 // v0.1 to v0.2 : we must change account reference by making a +1 to its index references
537 static void homebank_upgrade_to_v02(void)
541 DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") );
543 list
= g_list_first(GLOBALS
->ope_list
);
546 Transaction
*entry
= list
->data
;
549 list
= g_list_next(list
);
552 list
= g_list_first(GLOBALS
->arc_list
);
555 Archive
*entry
= list
->data
;
558 list
= g_list_next(list
);
562 // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738
563 static void homebank_upgrade_to_v03(void)
567 DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") );
569 list
= g_list_first(GLOBALS
->ope_list
);
572 Transaction
*entry
= list
->data
;
574 da_transaction_consistency(entry
);
575 list
= g_list_next(list
);
578 list
= g_list_first(GLOBALS
->arc_list
);
581 Archive
*entry
= list
->data
;
583 da_archive_consistency(entry
);
584 list
= g_list_next(list
);
588 static void homebank_upgrade_to_v04(void)
590 DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") );
592 GLOBALS
->arc_list
= da_archive_sort(GLOBALS
->arc_list
);
597 // we must assume kxferacc exists in archives for internal xfer : bug 528923
598 // if not, remove automation from the archive
599 static void homebank_upgrade_to_v05(void)
603 DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") );
605 list
= g_list_first(GLOBALS
->arc_list
);
608 Archive
*entry
= list
->data
;
610 da_archive_consistency(entry
);
611 list
= g_list_next(list
);
616 // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions
618 static void homebank_upgrade_to_v06(void)
622 DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") );
624 list
= g_list_first(GLOBALS
->ope_list
);
627 Transaction
*entry
= list
->data
;
628 da_transaction_consistency(entry
);
629 list
= g_list_next(list
);
632 list
= g_list_first(GLOBALS
->arc_list
);
635 Archive
*entry
= list
->data
;
636 da_archive_consistency(entry
);
637 list
= g_list_next(list
);
642 // v0.7 AF_BUDGET removed instead of AF_NOBUDGET
643 static void homebank_upgrade_to_v07(void)
647 DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") );
649 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
652 Account
*acc
= list
->data
;
654 if( acc
->flags
& AF_OLDBUDGET
) // budget include
656 acc
->flags
&= ~(AF_OLDBUDGET
);
660 acc
->flags
|= AF_NOBUDGET
;
663 list
= g_list_next(list
);
669 static void homebank_upgrade_to_v08(void)
673 DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") );
675 list
= g_list_first(GLOBALS
->ope_list
);
678 Transaction
*entry
= list
->data
;
679 da_transaction_consistency(entry
);
680 list
= g_list_next(list
);
687 // v0.6 to v0.7 : assign a default currency
689 static void homebank_upgrade_to_v08(void)
692 // set a base currency to the hbfile if not
693 g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
695 if(GLOBALS->kcur == 0)
697 //struct iso4217format *choice = ui_cur_select_dialog_new(GLOBALS->mainwindow);
698 struct iso4217format *curfmt = iso4217format_get(PREFS->curr_default);
701 curfmt = iso4217format_get_en_us();
704 Currency *item = currency_add_from_user(curfmt);
706 GLOBALS->kcur = item->key;
708 g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
710 // set every accounts to base currecny
711 GList *list = g_hash_table_get_values(GLOBALS->h_acc);
717 acc->kcur = item->key;
719 list = g_list_next(list);
729 // lower v0.6 : we must assume categories/payee exists
730 // and strong link to xfer
732 static void homebank_upgrade_lower_v06(void)
738 DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") );
740 list
= g_list_first(GLOBALS
->ope_list
);
743 Transaction
*entry
= list
->data
;
745 da_transaction_consistency(entry
);
747 //also strong link internal xfer
748 if(entry
->paymode
== PAYMODE_INTXFER
)
750 Transaction
*child
= transaction_old_get_child_transfer(entry
);
753 transaction_xfer_change_to_child(entry
, child
);
757 list
= g_list_next(list
);
761 lrul
= list
= g_hash_table_get_values(GLOBALS
->h_rul
);
764 Assign
*entry
= list
->data
;
766 cat
= da_cat_get(entry
->kcat
);
769 DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry
->kcat
) );
773 pay
= da_pay_get(entry
->kpay
);
776 DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry
->kpay
) );
781 list
= g_list_next(list
);
789 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
792 ** misc xml attributes methods
794 static void hb_xml_append_txt(GString
*gstring
, gchar
*attrname
, gchar
*value
)
796 if(value
!= NULL
&& *value
!= 0)
798 gchar
*escaped
= g_markup_escape_text(value
, -1);
799 g_string_append_printf(gstring
, "%s=\"%s\" ", attrname
, escaped
);
804 static void hb_xml_append_int0(GString
*gstring
, gchar
*attrname
, guint32 value
)
806 g_string_append_printf(gstring
, "%s=\"%d\" ", attrname
, value
);
809 static void hb_xml_append_int(GString
*gstring
, gchar
*attrname
, guint32 value
)
813 hb_xml_append_int0(gstring
, attrname
, value
);
817 static void hb_xml_append_amt(GString
*gstring
, gchar
*attrname
, gdouble amount
)
819 char buf
[G_ASCII_DTOSTR_BUF_SIZE
];
821 //we must use this, as fprintf use locale decimal settings and not '.'
822 g_ascii_dtostr (buf
, sizeof (buf
), amount
);
823 g_string_append_printf(gstring
, "%s=\"%s\" ", attrname
, buf
);
828 ** XML properties save
830 static void homebank_save_xml_prop(GIOChannel
*io
)
835 title
= GLOBALS
->owner
== NULL
? "" : GLOBALS
->owner
;
837 node
= g_string_sized_new(255);
839 g_string_assign(node
, "<properties ");
841 hb_xml_append_txt(node
, "title", title
);
842 hb_xml_append_int(node
, "car_category", GLOBALS
->vehicle_category
);
843 hb_xml_append_int0(node
, "auto_smode", GLOBALS
->auto_smode
);
844 hb_xml_append_int(node
, "auto_weekday", GLOBALS
->auto_weekday
);
845 hb_xml_append_int(node
, "auto_nbdays", GLOBALS
->auto_nbdays
);
847 g_string_append(node
, "/>\n");
849 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
851 g_string_free(node
, TRUE
);
859 static void homebank_save_xml_cur(GIOChannel *io)
863 char buf1[G_ASCII_DTOSTR_BUF_SIZE];
865 list = g_hash_table_get_values(GLOBALS->h_cur);
868 Currency *item = list->data;
872 tmpstr = g_markup_printf_escaped(
873 "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
882 g_ascii_dtostr (buf1, sizeof (buf1), item->rate),
886 g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
890 list = g_list_next(list);
900 static void homebank_save_xml_acc(GIOChannel
*io
)
905 node
= g_string_sized_new(255);
907 lacc
= list
= account_glist_sorted(0);
910 Account
*item
= list
->data
;
912 item
->flags
&= ~(AF_ADDED
|AF_CHANGED
); //remove flag
914 g_string_assign(node
, "<account ");
916 hb_xml_append_int(node
, "key", item
->key
);
917 hb_xml_append_int(node
, "flags", item
->flags
);
918 hb_xml_append_int(node
, "pos", item
->pos
);
919 hb_xml_append_int(node
, "type", item
->type
);
920 //hb_xml_append_int(node, "curr", item->kcur);
921 hb_xml_append_txt(node
, "name", item
->name
);
922 hb_xml_append_txt(node
, "number", item
->number
);
923 hb_xml_append_txt(node
, "bankname", item
->bankname
);
924 hb_xml_append_amt(node
, "initial", item
->initial
);
925 hb_xml_append_amt(node
, "minimum", item
->minimum
);
926 hb_xml_append_int(node
, "cheque1", item
->cheque1
);
927 hb_xml_append_int(node
, "cheque2", item
->cheque2
);
929 g_string_append(node
, "/>\n");
931 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
932 list
= g_list_next(list
);
935 g_string_free(node
, TRUE
);
941 static void homebank_save_xml_pay(GIOChannel
*io
)
946 lpay
= list
= payee_glist_sorted(0);
949 Payee
*item
= list
->data
;
953 tmpstr
= g_markup_printf_escaped("<pay key=\"%d\" name=\"%s\"/>\n",
958 g_io_channel_write_chars(io
, tmpstr
, -1, NULL
, NULL
);
962 list
= g_list_next(list
);
970 static void homebank_save_xml_cat(GIOChannel
*io
)
974 char buf
[G_ASCII_DTOSTR_BUF_SIZE
];
977 node
= g_string_sized_new(255);
979 lcat
= list
= category_glist_sorted(0);
982 Category
*item
= list
->data
;
986 g_string_assign(node
, "<cat ");
988 hb_xml_append_int(node
, "key", item
->key
);
989 hb_xml_append_int(node
, "parent", item
->parent
);
990 hb_xml_append_int(node
, "flags", item
->flags
);
991 hb_xml_append_txt(node
, "name", item
->name
);
995 if(item
->budget
[i
] != 0)
997 g_string_append_printf(node
,"b%d=\"%s\" ", i
, g_ascii_dtostr (buf
, sizeof (buf
), item
->budget
[i
]));
1001 g_string_append(node
, "/>\n");
1002 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1005 list
= g_list_next(list
);
1008 g_string_free(node
, TRUE
);
1014 static void homebank_save_xml_tag(GIOChannel
*io
)
1019 ltag
= list
= tag_glist_sorted(0);
1020 while (list
!= NULL
)
1022 Tag
*item
= list
->data
;
1026 tmpstr
= g_markup_printf_escaped("<tag key=\"%d\" name=\"%s\" />\n",
1031 g_io_channel_write_chars(io
, tmpstr
, -1, NULL
, NULL
);
1035 list
= g_list_next(list
);
1044 static void homebank_save_xml_asg(GIOChannel
*io
)
1049 node
= g_string_sized_new(255);
1051 lasg
= list
= assign_glist_sorted(0);
1052 while (list
!= NULL
)
1054 Assign
*item
= list
->data
;
1056 g_string_assign(node
, "<asg ");
1058 hb_xml_append_int(node
, "key" , item
->key
);
1059 hb_xml_append_int(node
, "flags" , item
->flags
);
1060 hb_xml_append_int(node
, "field" , item
->field
);
1061 hb_xml_append_txt(node
, "name" , item
->name
);
1062 hb_xml_append_int(node
, "payee" , item
->kpay
);
1063 hb_xml_append_int(node
, "category", item
->kcat
);
1064 //hb_xml_append_int(node, "paymode" , item->paymode);
1066 g_string_append(node
, "/>\n");
1068 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1070 list
= g_list_next(list
);
1073 g_string_free(node
, TRUE
);
1081 static void homebank_save_xml_arc(GIOChannel
*io
)
1086 node
= g_string_sized_new(255);
1088 list
= g_list_first(GLOBALS
->arc_list
);
1089 while (list
!= NULL
)
1091 Archive
*item
= list
->data
;
1093 g_string_assign(node
, "<fav ");
1095 hb_xml_append_amt(node
, "amount", item
->amount
);
1096 hb_xml_append_int(node
, "account", item
->kacc
);
1097 hb_xml_append_int(node
, "dst_account", item
->kxferacc
);
1098 hb_xml_append_int(node
, "paymode", item
->paymode
);
1099 hb_xml_append_int(node
, "flags", item
->flags
);
1100 hb_xml_append_int(node
, "payee", item
->kpay
);
1101 hb_xml_append_int(node
, "category", item
->kcat
);
1102 hb_xml_append_txt(node
, "wording", item
->wording
);
1103 hb_xml_append_int(node
, "nextdate", item
->nextdate
);
1104 hb_xml_append_int(node
, "every", item
->every
);
1105 hb_xml_append_int(node
, "unit", item
->unit
);
1106 hb_xml_append_int(node
, "limit", item
->limit
);
1107 hb_xml_append_int(node
, "weekend", item
->weekend
);
1109 g_string_append(node
, "/>\n");
1111 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1112 list
= g_list_next(list
);
1114 g_string_free(node
, TRUE
);
1119 ** XML transaction save
1121 static void homebank_save_xml_ope(GIOChannel
*io
)
1127 node
= g_string_sized_new(255);
1129 list
= g_list_first(GLOBALS
->ope_list
);
1130 while (list
!= NULL
)
1132 Transaction
*item
= list
->data
;
1134 item
->flags
&= ~(OF_AUTO
|OF_ADDED
|OF_CHANGED
); //remove flag
1135 tagstr
= transaction_tags_tostring(item
);
1137 g_string_assign(node
, "<ope ");
1139 hb_xml_append_int(node
, "date", item
->date
);
1140 hb_xml_append_amt(node
, "amount", item
->amount
);
1141 hb_xml_append_int(node
, "account", item
->kacc
);
1142 hb_xml_append_int(node
, "dst_account", item
->kxferacc
);
1143 hb_xml_append_int(node
, "paymode", item
->paymode
);
1144 hb_xml_append_int(node
, "flags", item
->flags
);
1145 hb_xml_append_int(node
, "payee", item
->kpay
);
1146 hb_xml_append_int(node
, "category", item
->kcat
);
1147 hb_xml_append_txt(node
, "wording", item
->wording
);
1148 hb_xml_append_txt(node
, "info", item
->info
);
1149 hb_xml_append_txt(node
, "tags", tagstr
);
1150 hb_xml_append_int(node
, "kxfer", item
->kxfer
);
1152 if(da_transaction_splits_count(item
) > 0)
1154 gchar
*cats
, *amounts
, *memos
;
1156 transaction_splits_tostring(item
, &cats
, &amounts
, &memos
);
1157 g_string_append_printf(node
, "scat=\"%s\" ", cats
);
1158 g_string_append_printf(node
, "samt=\"%s\" ", amounts
);
1161 gchar
*escaped
= g_markup_escape_text(memos
, -1);
1162 g_string_append_printf(node
, "smem=\"%s\" ", escaped
);
1170 g_string_append(node
, "/>\n");
1173 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1174 list
= g_list_next(list
);
1176 g_string_free(node
, TRUE
);
1180 ** XML save homebank file: hbfile
1182 gint
homebank_save_xml(gchar
*filename
)
1185 char buf1
[G_ASCII_DTOSTR_BUF_SIZE
];
1187 gint retval
= XML_OK
;
1189 io
= g_io_channel_new_file(filename
, "w", NULL
);
1192 g_message("file error on: %s", filename
);
1193 retval
= XML_IO_ERROR
;
1197 g_io_channel_write_chars(io
, "<?xml version=\"1.0\"?>\n", -1, NULL
, NULL
);
1199 outstr
= g_strdup_printf("<homebank v=\"%s\">\n", g_ascii_dtostr (buf1
, sizeof (buf1
), FILE_VERSION
));
1200 g_io_channel_write_chars(io
, outstr
, -1, NULL
, NULL
);
1203 homebank_save_xml_prop(io
);
1204 //homebank_save_xml_cur(io);
1205 homebank_save_xml_acc(io
);
1206 homebank_save_xml_pay(io
);
1207 homebank_save_xml_cat(io
);
1208 homebank_save_xml_tag(io
);
1209 homebank_save_xml_asg(io
);
1210 homebank_save_xml_arc(io
);
1211 homebank_save_xml_ope(io
);
1213 g_io_channel_write_chars(io
, "</homebank>\n", -1, NULL
, NULL
);
1215 g_io_channel_unref (io
);