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"
28 /****************************************************************************/
30 /****************************************************************************/
39 /* our global datas */
40 extern struct HomeBank
*GLOBALS
;
41 extern struct Preferences
*PREFS
;
43 typedef struct _ParseContext ParseContext
;
50 static void homebank_upgrade_to_v02(void);
51 static void homebank_upgrade_to_v03(void);
52 static void homebank_upgrade_to_v04(void);
53 static void homebank_upgrade_to_v05(void);
54 static void homebank_upgrade_lower_v06(void);
55 static void homebank_upgrade_to_v06(void);
56 static void homebank_upgrade_to_v07(void);
57 static void homebank_upgrade_to_v08(void);
60 start_element_handler (GMarkupParseContext
*context
,
61 const gchar
*element_name
,
62 const gchar
**attribute_names
,
63 const gchar
**attribute_values
,
67 ParseContext
*ctx
= user_data
;
68 //GtkUIManager *self = ctx->self;
71 //DB( g_print("** start element: %s\n", element_name) );
73 switch(element_name
[0])
79 if(!strcmp (element_name, "homebank"))
81 if(!strcmp (attribute_names[0], "v" ))
83 version = g_ascii_strtod(attribute_values[0], NULL);
84 DB( g_print(" version %f\n", version) );
93 if(!strcmp (element_name
, "account"))
95 Account
*entry
= da_acc_malloc();
97 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
99 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
101 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
102 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
103 else if(!strcmp (attribute_names
[i
], "pos" )) { entry
->pos
= atoi(attribute_values
[i
]); }
104 else if(!strcmp (attribute_names
[i
], "type" )) { entry
->type
= atoi(attribute_values
[i
]); }
105 //else if(!strcmp (attribute_names[i], "curr" )) { entry->kcur = atoi(attribute_values[i]); }
106 else if(!strcmp (attribute_names
[i
], "name" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->name
= g_strdup(attribute_values
[i
]); }
107 else if(!strcmp (attribute_names
[i
], "number" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->number
= g_strdup(attribute_values
[i
]); }
108 else if(!strcmp (attribute_names
[i
], "bankname")) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->bankname
= g_strdup(attribute_values
[i
]); }
109 else if(!strcmp (attribute_names
[i
], "initial" )) { entry
->initial
= g_ascii_strtod(attribute_values
[i
], NULL
); }
110 else if(!strcmp (attribute_names
[i
], "minimum" )) { entry
->minimum
= g_ascii_strtod(attribute_values
[i
], NULL
); }
111 else if(!strcmp (attribute_names
[i
], "cheque1" )) { entry
->cheque1
= atoi(attribute_values
[i
]); }
112 else if(!strcmp (attribute_names
[i
], "cheque2" )) { entry
->cheque2
= atoi(attribute_values
[i
]); }
116 //version upgrade: type was added in 0.2
117 //todo: for stock account
121 entry->type = ACC_TYPE_BANK;
122 DB( g_print(" acctype forced to BANK\n") );
126 DB( g_print(" version %f\n", ctx
->version
) );
128 //upgrade to v0.2 file
129 // we must change account reference by making a +1 to its index references
130 if( ctx
->version
== 0.1 )
133 entry
->pos
= entry
->key
;
136 //all attribute loaded: append
137 da_acc_insert(entry
);
141 else if(!strcmp (element_name
, "asg"))
143 Assign
*entry
= da_asg_malloc();
146 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
148 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
150 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
151 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
152 else if(!strcmp (attribute_names
[i
], "field" )) { entry
->field
= atoi(attribute_values
[i
]); }
153 else if(!strcmp (attribute_names
[i
], "name" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->name
= g_strdup(attribute_values
[i
]); }
154 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
155 else if(!strcmp (attribute_names
[i
], "category")) { entry
->kcat
= atoi(attribute_values
[i
]); }
156 //else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
158 else if(!strcmp (attribute_names
[i
], "exact" )) { exact
= atoi(attribute_values
[i
]); }
161 /* in v08 exact moved to flag */
162 if( ctx
->version
<= 0.7)
164 entry
->flags
= (ASGF_DOCAT
|ASGF_DOPAY
);
166 entry
->flags
|= ASGF_EXACT
;
169 //all attribute loaded: append
170 da_asg_append(entry
);
179 if(!strcmp (element_name
, "pay"))
181 Payee
*entry
= da_pay_malloc();
183 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
185 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
187 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
188 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
189 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
192 //all attribute loaded: append
193 da_pay_insert(entry
);
196 else if(!strcmp (element_name
, "properties"))
198 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
200 if(!strcmp (attribute_names
[i
], "title" )) { g_free(GLOBALS
->owner
); GLOBALS
->owner
= g_strdup(attribute_values
[i
]); }
201 //else if(!strcmp (attribute_names[i], "curr" )) { GLOBALS->kcur = atoi(attribute_values[i]); }
202 else if(!strcmp (attribute_names
[i
], "car_category")) { GLOBALS
->vehicle_category
= atoi(attribute_values
[i
]); }
203 else if(!strcmp (attribute_names
[i
], "auto_smode" )) { GLOBALS
->auto_smode
= atoi(attribute_values
[i
]); }
204 else if(!strcmp (attribute_names
[i
], "auto_weekday")) { GLOBALS
->auto_weekday
= atoi(attribute_values
[i
]); }
205 else if(!strcmp (attribute_names
[i
], "auto_nbdays" )) { GLOBALS
->auto_nbdays
= atoi(attribute_values
[i
]); }
213 if(!strcmp (element_name
, "cat"))
215 Category
*entry
= da_cat_malloc();
218 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
220 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
222 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
223 else if(!strcmp (attribute_names
[i
], "parent")) { entry
->parent
= atoi(attribute_values
[i
]); }
224 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
225 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
232 tmpname
= g_strdup_printf ("b%d", j
);
233 if(!(strcmp (attribute_names
[i
], tmpname
))) { entry
->budget
[j
] = g_ascii_strtod(attribute_values
[i
], NULL
); }
236 if(entry
->budget
[j
]) budget
= TRUE
;
239 entry
->flags
|= GF_BUDGET
;
243 //all attribute loaded: append
244 da_cat_insert( entry
);
246 /* else if(!strcmp (element_name, "cur"))
248 Currency *entry = da_cur_malloc ();
250 for (i = 0; attribute_names[i] != NULL; i++)
252 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
254 if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
255 else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
256 else if(!strcmp (attribute_names[i], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); }
257 else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[i]); }
258 else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); }
259 else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); }
260 else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); }
261 else if(!strcmp (attribute_names[i], "frac" )) { entry->frac_digits = atoi(attribute_values[i]); }
262 else if(!strcmp (attribute_names[i], "rate" )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); }
263 else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); }
267 //all attribute loaded: append
268 da_cur_insert (entry);
276 if(!strcmp (element_name
, "tags"))
278 Tag
*entry
= da_tag_malloc();
280 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
282 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
284 if(!strcmp (attribute_names
[i
], "key" )) { entry
->key
= atoi(attribute_values
[i
]); }
285 //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
286 else if(!strcmp (attribute_names
[i
], "name" )) { entry
->name
= g_strdup(attribute_values
[i
]); }
289 //all attribute loaded: append
290 da_tag_insert(entry
);
297 if(!strcmp (element_name
, "fav"))
299 Archive
*entry
= da_archive_malloc();
301 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
303 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
305 if(!strcmp (attribute_names
[i
], "amount" )) { entry
->amount
= g_ascii_strtod(attribute_values
[i
], NULL
); }
306 else if(!strcmp (attribute_names
[i
], "account" )) { entry
->kacc
= atoi(attribute_values
[i
]); }
307 else if(!strcmp (attribute_names
[i
], "dst_account")) { entry
->kxferacc
= atoi(attribute_values
[i
]); }
308 else if(!strcmp (attribute_names
[i
], "paymode" )) { entry
->paymode
= atoi(attribute_values
[i
]); }
309 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
310 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
311 else if(!strcmp (attribute_names
[i
], "category" )) { entry
->kcat
= atoi(attribute_values
[i
]); }
312 else if(!strcmp (attribute_names
[i
], "wording" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->wording
= g_strdup(attribute_values
[i
]); }
313 else if(!strcmp (attribute_names
[i
], "nextdate" )) { entry
->nextdate
= atoi(attribute_values
[i
]); }
314 else if(!strcmp (attribute_names
[i
], "every" )) { entry
->every
= atoi(attribute_values
[i
]); }
315 else if(!strcmp (attribute_names
[i
], "unit" )) { entry
->unit
= atoi(attribute_values
[i
]); }
316 else if(!strcmp (attribute_names
[i
], "limit" )) { entry
->limit
= atoi(attribute_values
[i
]); }
317 else if(!strcmp (attribute_names
[i
], "weekend" )) { entry
->weekend
= atoi(attribute_values
[i
]); }
321 //all attribute loaded: append
322 GLOBALS
->arc_list
= g_list_append(GLOBALS
->arc_list
, entry
);
337 if(!strcmp (element_name
, "ope"))
339 Transaction
*entry
= da_transaction_malloc();
343 gboolean split
= FALSE
;
345 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
347 //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
349 if(!strcmp (attribute_names
[i
], "date" )) { entry
->date
= atoi(attribute_values
[i
]); }
350 else if(!strcmp (attribute_names
[i
], "amount" )) { entry
->amount
= g_ascii_strtod(attribute_values
[i
], NULL
); }
351 else if(!strcmp (attribute_names
[i
], "account" )) { entry
->kacc
= atoi(attribute_values
[i
]); }
352 else if(!strcmp (attribute_names
[i
], "dst_account")) { entry
->kxferacc
= atoi(attribute_values
[i
]); }
353 else if(!strcmp (attribute_names
[i
], "paymode" )) { entry
->paymode
= atoi(attribute_values
[i
]); }
354 else if(!strcmp (attribute_names
[i
], "flags" )) { entry
->flags
= atoi(attribute_values
[i
]); }
355 else if(!strcmp (attribute_names
[i
], "payee" )) { entry
->kpay
= atoi(attribute_values
[i
]); }
356 else if(!strcmp (attribute_names
[i
], "category" )) { entry
->kcat
= atoi(attribute_values
[i
]); }
357 else if(!strcmp (attribute_names
[i
], "wording" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->wording
= g_strdup(attribute_values
[i
]); }
358 else if(!strcmp (attribute_names
[i
], "info" )) { if(strcmp(attribute_values
[i
],"(null)") && attribute_values
[i
] != NULL
) entry
->info
= g_strdup(attribute_values
[i
]); }
359 else if(!strcmp (attribute_names
[i
], "tags" ))
361 if(attribute_values
[i
] != NULL
&& strlen(attribute_values
[i
]) > 0 && strcmp(attribute_values
[i
],"(null)") != 0 )
363 transaction_tags_parse(entry
, attribute_values
[i
]);
366 else if(!strcmp (attribute_names
[i
], "kxfer" )) { entry
->kxfer
= atoi(attribute_values
[i
]); }
367 else if(!strcmp (attribute_names
[i
], "scat" )) { scat
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
368 else if(!strcmp (attribute_names
[i
], "samt" )) { samt
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
369 else if(!strcmp (attribute_names
[i
], "smem" )) { smem
= (gchar
*)attribute_values
[i
]; split
= TRUE
; }
373 //if(entry->kcat < 0)
378 transaction_splits_parse(entry
, scat
, samt
, smem
);
381 //all attribute loaded: append
382 // we use prepend here, the list will be reversed later for perf reason
383 da_transaction_prepend(entry
);
396 end_element_handler (GMarkupParseContext *context,
397 const gchar *element_name,
401 ParseContext *ctx = user_data;
403 //DB( g_print("-- end element: %s\n", element_name) );
409 static GMarkupParser hb_parser
= {
410 start_element_handler
,
411 NULL
, //end_element_handler,
412 NULL
, //text_handler,
418 ** XML load homebank file: hbfile
420 gint
homebank_load_xml(gchar
*filename
)
425 GError
*error
= NULL
;
426 ParseContext ctx
= { 0 };
427 GMarkupParseContext
*context
;
430 DB( g_print("\n[hb-xml] homebank_load_xml\n") );
432 GValue filename_val
= G_VALUE_INIT
;
433 ext_hook("load_file", EXT_STRING(&filename_val
, filename
), NULL
);
436 if (!g_file_get_contents (filename
, &buffer
, &length
, &error
))
438 //g_message ("%s", error->message);
439 retval
= XML_IO_ERROR
;
440 g_error_free (error
);
447 /* v3.4 add :: prevent load of future file version */
448 v_buffer
= g_strstr_len(buffer
, 50, "<homebank v=");
449 if( v_buffer
== NULL
)
450 return XML_FILE_ERROR
;
452 DB( g_print("- id line: --(%.50s)\n\n", v_buffer
) );
454 version
= g_ascii_strtod(v_buffer
+13, NULL
); /* a little hacky, but works ! */
458 ctx
.version
= version
;
460 if( version
> FILE_VERSION
)
462 DB( g_print("- failed: version %f is not supported (max is %f)\n", version
, FILE_VERSION
) );
463 return XML_VERSION_ERROR
;
467 DB( g_print("- ok : version=%.1f\n", version
) );
469 /* 1st: validate the file is well in utf-8 */
470 DB( g_print("- ensure UTF-8\n") );
471 buffer
= homebank_utf8_ensure(buffer
);
473 /* then process the buffer */
475 GTimer
*t
= g_timer_new();
476 g_print("- start parse\n");
479 context
= g_markup_parse_context_new (&hb_parser
, 0, &ctx
, NULL
);
482 rc
= g_markup_parse_context_parse (context
, buffer
, length
, &error
);
485 g_print("failed: %s\n", error
->message
);
490 g_markup_parse_context_end_parse(context
, &error
);
493 g_print("failed: %s\n", error
->message
);
496 g_markup_parse_context_free (context
);
499 //reverse the glist (see g_list append idiom to perf for reason
500 // we use prepend and then reverse
501 GLOBALS
->ope_list
= g_list_reverse(GLOBALS
->ope_list
);
503 DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t
, NULL
)) );
504 DB( g_timer_destroy (t
) );
506 /* file upgrade / bugfix */
508 homebank_upgrade_to_v02();
510 homebank_upgrade_to_v03();
512 homebank_upgrade_to_v04();
514 homebank_upgrade_to_v05();
517 homebank_upgrade_to_v06();
518 homebank_upgrade_lower_v06();
522 homebank_upgrade_to_v07();
523 hbfile_sanity_check();
526 homebank_upgrade_to_v08();
528 hbfile_sanity_check();
539 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
541 // v0.1 to v0.2 : we must change account reference by making a +1 to its index references
542 static void homebank_upgrade_to_v02(void)
546 DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") );
548 list
= g_list_first(GLOBALS
->ope_list
);
551 Transaction
*entry
= list
->data
;
554 list
= g_list_next(list
);
557 list
= g_list_first(GLOBALS
->arc_list
);
560 Archive
*entry
= list
->data
;
563 list
= g_list_next(list
);
567 // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738
568 static void homebank_upgrade_to_v03(void)
572 DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") );
574 list
= g_list_first(GLOBALS
->ope_list
);
577 Transaction
*entry
= list
->data
;
579 da_transaction_consistency(entry
);
580 list
= g_list_next(list
);
583 list
= g_list_first(GLOBALS
->arc_list
);
586 Archive
*entry
= list
->data
;
588 da_archive_consistency(entry
);
589 list
= g_list_next(list
);
593 static void homebank_upgrade_to_v04(void)
595 DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") );
597 GLOBALS
->arc_list
= da_archive_sort(GLOBALS
->arc_list
);
602 // we must assume kxferacc exists in archives for internal xfer : bug 528923
603 // if not, remove automation from the archive
604 static void homebank_upgrade_to_v05(void)
608 DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") );
610 list
= g_list_first(GLOBALS
->arc_list
);
613 Archive
*entry
= list
->data
;
615 da_archive_consistency(entry
);
616 list
= g_list_next(list
);
621 // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions
623 static void homebank_upgrade_to_v06(void)
627 DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") );
629 list
= g_list_first(GLOBALS
->ope_list
);
632 Transaction
*entry
= list
->data
;
633 da_transaction_consistency(entry
);
634 list
= g_list_next(list
);
637 list
= g_list_first(GLOBALS
->arc_list
);
640 Archive
*entry
= list
->data
;
641 da_archive_consistency(entry
);
642 list
= g_list_next(list
);
647 // v0.7 AF_BUDGET removed instead of AF_NOBUDGET
648 static void homebank_upgrade_to_v07(void)
652 DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") );
654 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
657 Account
*acc
= list
->data
;
659 if( acc
->flags
& AF_OLDBUDGET
) // budget include
661 acc
->flags
&= ~(AF_OLDBUDGET
);
665 acc
->flags
|= AF_NOBUDGET
;
668 list
= g_list_next(list
);
674 static void homebank_upgrade_to_v08(void)
678 DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") );
680 list
= g_list_first(GLOBALS
->ope_list
);
683 Transaction
*entry
= list
->data
;
684 da_transaction_consistency(entry
);
685 list
= g_list_next(list
);
692 // v0.6 to v0.7 : assign a default currency
694 static void homebank_upgrade_to_v08(void)
697 // set a base currency to the hbfile if not
698 g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
700 if(GLOBALS->kcur == 0)
702 //struct iso4217format *choice = ui_cur_select_dialog_new(GLOBALS->mainwindow);
703 struct iso4217format *curfmt = iso4217format_get(PREFS->curr_default);
706 curfmt = iso4217format_get_en_us();
709 Currency *item = currency_add_from_user(curfmt);
711 GLOBALS->kcur = item->key;
713 g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
715 // set every accounts to base currecny
716 GList *list = g_hash_table_get_values(GLOBALS->h_acc);
722 acc->kcur = item->key;
724 list = g_list_next(list);
734 // lower v0.6 : we must assume categories/payee exists
735 // and strong link to xfer
737 static void homebank_upgrade_lower_v06(void)
743 DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") );
745 list
= g_list_first(GLOBALS
->ope_list
);
748 Transaction
*entry
= list
->data
;
750 da_transaction_consistency(entry
);
752 //also strong link internal xfer
753 if(entry
->paymode
== PAYMODE_INTXFER
)
755 Transaction
*child
= transaction_old_get_child_transfer(entry
);
758 transaction_xfer_change_to_child(entry
, child
);
762 list
= g_list_next(list
);
766 lrul
= list
= g_hash_table_get_values(GLOBALS
->h_rul
);
769 Assign
*entry
= list
->data
;
771 cat
= da_cat_get(entry
->kcat
);
774 DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry
->kcat
) );
778 pay
= da_pay_get(entry
->kpay
);
781 DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry
->kpay
) );
786 list
= g_list_next(list
);
794 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
797 ** misc xml attributes methods
799 static void hb_xml_append_txt(GString
*gstring
, gchar
*attrname
, gchar
*value
)
801 if(value
!= NULL
&& *value
!= 0)
803 gchar
*escaped
= g_markup_escape_text(value
, -1);
804 g_string_append_printf(gstring
, "%s=\"%s\" ", attrname
, escaped
);
809 static void hb_xml_append_int0(GString
*gstring
, gchar
*attrname
, guint32 value
)
811 g_string_append_printf(gstring
, "%s=\"%d\" ", attrname
, value
);
814 static void hb_xml_append_int(GString
*gstring
, gchar
*attrname
, guint32 value
)
818 hb_xml_append_int0(gstring
, attrname
, value
);
822 static void hb_xml_append_amt(GString
*gstring
, gchar
*attrname
, gdouble amount
)
824 char buf
[G_ASCII_DTOSTR_BUF_SIZE
];
826 //we must use this, as fprintf use locale decimal settings and not '.'
827 g_ascii_dtostr (buf
, sizeof (buf
), amount
);
828 g_string_append_printf(gstring
, "%s=\"%s\" ", attrname
, buf
);
833 ** XML properties save
835 static void homebank_save_xml_prop(GIOChannel
*io
)
840 title
= GLOBALS
->owner
== NULL
? "" : GLOBALS
->owner
;
842 node
= g_string_sized_new(255);
844 g_string_assign(node
, "<properties ");
846 hb_xml_append_txt(node
, "title", title
);
847 hb_xml_append_int(node
, "car_category", GLOBALS
->vehicle_category
);
848 hb_xml_append_int0(node
, "auto_smode", GLOBALS
->auto_smode
);
849 hb_xml_append_int(node
, "auto_weekday", GLOBALS
->auto_weekday
);
850 hb_xml_append_int(node
, "auto_nbdays", GLOBALS
->auto_nbdays
);
852 g_string_append(node
, "/>\n");
854 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
856 g_string_free(node
, TRUE
);
864 static void homebank_save_xml_cur(GIOChannel *io)
868 char buf1[G_ASCII_DTOSTR_BUF_SIZE];
870 list = g_hash_table_get_values(GLOBALS->h_cur);
873 Currency *item = list->data;
877 tmpstr = g_markup_printf_escaped(
878 "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
887 g_ascii_dtostr (buf1, sizeof (buf1), item->rate),
891 g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
895 list = g_list_next(list);
905 static void homebank_save_xml_acc(GIOChannel
*io
)
910 node
= g_string_sized_new(255);
912 lacc
= list
= account_glist_sorted(0);
915 Account
*item
= list
->data
;
917 item
->flags
&= ~(AF_ADDED
|AF_CHANGED
); //remove flag
919 g_string_assign(node
, "<account ");
921 hb_xml_append_int(node
, "key", item
->key
);
922 hb_xml_append_int(node
, "flags", item
->flags
);
923 hb_xml_append_int(node
, "pos", item
->pos
);
924 hb_xml_append_int(node
, "type", item
->type
);
925 //hb_xml_append_int(node, "curr", item->kcur);
926 hb_xml_append_txt(node
, "name", item
->name
);
927 hb_xml_append_txt(node
, "number", item
->number
);
928 hb_xml_append_txt(node
, "bankname", item
->bankname
);
929 hb_xml_append_amt(node
, "initial", item
->initial
);
930 hb_xml_append_amt(node
, "minimum", item
->minimum
);
931 hb_xml_append_int(node
, "cheque1", item
->cheque1
);
932 hb_xml_append_int(node
, "cheque2", item
->cheque2
);
934 g_string_append(node
, "/>\n");
936 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
937 list
= g_list_next(list
);
940 g_string_free(node
, TRUE
);
946 static void homebank_save_xml_pay(GIOChannel
*io
)
951 lpay
= list
= payee_glist_sorted(0);
954 Payee
*item
= list
->data
;
958 tmpstr
= g_markup_printf_escaped("<pay key=\"%d\" name=\"%s\"/>\n",
963 g_io_channel_write_chars(io
, tmpstr
, -1, NULL
, NULL
);
967 list
= g_list_next(list
);
975 static void homebank_save_xml_cat(GIOChannel
*io
)
979 char buf
[G_ASCII_DTOSTR_BUF_SIZE
];
982 node
= g_string_sized_new(255);
984 lcat
= list
= category_glist_sorted(0);
987 Category
*item
= list
->data
;
991 g_string_assign(node
, "<cat ");
993 hb_xml_append_int(node
, "key", item
->key
);
994 hb_xml_append_int(node
, "parent", item
->parent
);
995 hb_xml_append_int(node
, "flags", item
->flags
);
996 hb_xml_append_txt(node
, "name", item
->name
);
1000 if(item
->budget
[i
] != 0)
1002 g_string_append_printf(node
,"b%d=\"%s\" ", i
, g_ascii_dtostr (buf
, sizeof (buf
), item
->budget
[i
]));
1006 g_string_append(node
, "/>\n");
1007 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1010 list
= g_list_next(list
);
1013 g_string_free(node
, TRUE
);
1019 static void homebank_save_xml_tag(GIOChannel
*io
)
1024 ltag
= list
= tag_glist_sorted(0);
1025 while (list
!= NULL
)
1027 Tag
*item
= list
->data
;
1031 tmpstr
= g_markup_printf_escaped("<tag key=\"%d\" name=\"%s\" />\n",
1036 g_io_channel_write_chars(io
, tmpstr
, -1, NULL
, NULL
);
1040 list
= g_list_next(list
);
1049 static void homebank_save_xml_asg(GIOChannel
*io
)
1054 node
= g_string_sized_new(255);
1056 lasg
= list
= assign_glist_sorted(0);
1057 while (list
!= NULL
)
1059 Assign
*item
= list
->data
;
1061 g_string_assign(node
, "<asg ");
1063 hb_xml_append_int(node
, "key" , item
->key
);
1064 hb_xml_append_int(node
, "flags" , item
->flags
);
1065 hb_xml_append_int(node
, "field" , item
->field
);
1066 hb_xml_append_txt(node
, "name" , item
->name
);
1067 hb_xml_append_int(node
, "payee" , item
->kpay
);
1068 hb_xml_append_int(node
, "category", item
->kcat
);
1069 //hb_xml_append_int(node, "paymode" , item->paymode);
1071 g_string_append(node
, "/>\n");
1073 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1075 list
= g_list_next(list
);
1078 g_string_free(node
, TRUE
);
1086 static void homebank_save_xml_arc(GIOChannel
*io
)
1091 node
= g_string_sized_new(255);
1093 list
= g_list_first(GLOBALS
->arc_list
);
1094 while (list
!= NULL
)
1096 Archive
*item
= list
->data
;
1098 g_string_assign(node
, "<fav ");
1100 hb_xml_append_amt(node
, "amount", item
->amount
);
1101 hb_xml_append_int(node
, "account", item
->kacc
);
1102 hb_xml_append_int(node
, "dst_account", item
->kxferacc
);
1103 hb_xml_append_int(node
, "paymode", item
->paymode
);
1104 hb_xml_append_int(node
, "flags", item
->flags
);
1105 hb_xml_append_int(node
, "payee", item
->kpay
);
1106 hb_xml_append_int(node
, "category", item
->kcat
);
1107 hb_xml_append_txt(node
, "wording", item
->wording
);
1108 hb_xml_append_int(node
, "nextdate", item
->nextdate
);
1109 hb_xml_append_int(node
, "every", item
->every
);
1110 hb_xml_append_int(node
, "unit", item
->unit
);
1111 hb_xml_append_int(node
, "limit", item
->limit
);
1112 hb_xml_append_int(node
, "weekend", item
->weekend
);
1114 g_string_append(node
, "/>\n");
1116 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1117 list
= g_list_next(list
);
1119 g_string_free(node
, TRUE
);
1124 ** XML transaction save
1126 static void homebank_save_xml_ope(GIOChannel
*io
)
1132 node
= g_string_sized_new(255);
1134 list
= g_list_first(GLOBALS
->ope_list
);
1135 while (list
!= NULL
)
1137 Transaction
*item
= list
->data
;
1139 item
->flags
&= ~(OF_AUTO
|OF_ADDED
|OF_CHANGED
); //remove flag
1140 tagstr
= transaction_tags_tostring(item
);
1142 g_string_assign(node
, "<ope ");
1144 hb_xml_append_int(node
, "date", item
->date
);
1145 hb_xml_append_amt(node
, "amount", item
->amount
);
1146 hb_xml_append_int(node
, "account", item
->kacc
);
1147 hb_xml_append_int(node
, "dst_account", item
->kxferacc
);
1148 hb_xml_append_int(node
, "paymode", item
->paymode
);
1149 hb_xml_append_int(node
, "flags", item
->flags
);
1150 hb_xml_append_int(node
, "payee", item
->kpay
);
1151 hb_xml_append_int(node
, "category", item
->kcat
);
1152 hb_xml_append_txt(node
, "wording", item
->wording
);
1153 hb_xml_append_txt(node
, "info", item
->info
);
1154 hb_xml_append_txt(node
, "tags", tagstr
);
1155 hb_xml_append_int(node
, "kxfer", item
->kxfer
);
1157 if(da_transaction_splits_count(item
) > 0)
1159 gchar
*cats
, *amounts
, *memos
;
1161 transaction_splits_tostring(item
, &cats
, &amounts
, &memos
);
1162 g_string_append_printf(node
, "scat=\"%s\" ", cats
);
1163 g_string_append_printf(node
, "samt=\"%s\" ", amounts
);
1166 gchar
*escaped
= g_markup_escape_text(memos
, -1);
1167 g_string_append_printf(node
, "smem=\"%s\" ", escaped
);
1175 g_string_append(node
, "/>\n");
1178 g_io_channel_write_chars(io
, node
->str
, -1, NULL
, NULL
);
1179 list
= g_list_next(list
);
1181 g_string_free(node
, TRUE
);
1185 ** XML save homebank file: hbfile
1187 gint
homebank_save_xml(gchar
*filename
)
1190 char buf1
[G_ASCII_DTOSTR_BUF_SIZE
];
1192 gint retval
= XML_OK
;
1194 GValue filename_val
= G_VALUE_INIT
;
1195 ext_hook("save_file", EXT_STRING(&filename_val
, filename
), NULL
);
1197 io
= g_io_channel_new_file(filename
, "w", NULL
);
1200 g_message("file error on: %s", filename
);
1201 retval
= XML_IO_ERROR
;
1205 g_io_channel_write_chars(io
, "<?xml version=\"1.0\"?>\n", -1, NULL
, NULL
);
1207 outstr
= g_strdup_printf("<homebank v=\"%s\">\n", g_ascii_dtostr (buf1
, sizeof (buf1
), FILE_VERSION
));
1208 g_io_channel_write_chars(io
, outstr
, -1, NULL
, NULL
);
1211 homebank_save_xml_prop(io
);
1212 //homebank_save_xml_cur(io);
1213 homebank_save_xml_acc(io
);
1214 homebank_save_xml_pay(io
);
1215 homebank_save_xml_cat(io
);
1216 homebank_save_xml_tag(io
);
1217 homebank_save_xml_asg(io
);
1218 homebank_save_xml_arc(io
);
1219 homebank_save_xml_ope(io
);
1221 g_io_channel_write_chars(io
, "</homebank>\n", -1, NULL
, NULL
);
1223 g_io_channel_unref (io
);