00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00035 #define _GNU_SOURCE
00036 #include "config.h"
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <regex.h>
00040 #include <ctype.h>
00041 #include <glib.h>
00042 #include <glib/gi18n.h>
00043 #include <glib/gprintf.h>
00044 #include <qof.h>
00045 #include <popt.h>
00046 #include "pi-source.h"
00047 #include "pi-debug.h"
00048 #include "pi-socket.h"
00049 #include "pi-file.h"
00050 #include "pi-header.h"
00051 #include "pi-util.h"
00052 #include "qof-main.h"
00053 #include "palm.h"
00054 #include "pilot-qof.h"
00055 #include "pilot-todo.h"
00056 #include "qof-address.h"
00057 #include "qof-datebook.h"
00058 #ifdef HAVE_QOFEXPENSES
00059 #include <qof-expenses.h>
00060 #endif
00061 #include "pilot-expenses.h"
00062
00064 static QofLogModule log_module = PQ_MOD_CLI;
00066 static GList *pilot_modules = NULL;
00067
00068 static const gchar *env_pilotport = "PILOTPORT";
00069
00070 #define ARGUMENT_BAD_OPTION 17227
00071
00072 #define EXCLUDE_REPEATER_SQL "SELECT * from pilot_datebook " \
00073 "where DATEBOOK_REPEATER == TRUE;"
00074
00075 #define ENUM_LIST_Q(_) \
00076 _(qof_op_noop, = 0) \
00077 _(qof_op_offline, ) \
00078 _(qof_op_list,) \
00079 _(qof_op_hotsync,) \
00080 _(qof_op_empty,) \
00081 _(qof_op_category,) \
00082 _(qof_op_database,) \
00083 _(qof_op_time,) \
00084 _(qof_op_exclude,) \
00085 _(qof_op_sql,) \
00086 _(qof_op_sql_file,) \
00087 _(qof_op_write, ) \
00088 _(qof_op_upload, ) \
00089 _(qof_op_explain,) \
00090 _(qof_op_vers,) \
00091 _(qof_op_compress,) \
00092 _(qof_op_debug,) \
00093 _(qof_op_inv_city,) \
00094 _(qof_op_inv_vendor,) \
00095 _(qof_op_use_locale,)
00096
00097 DEFINE_ENUM (qof_op_type, ENUM_LIST_Q)
00098
00099 static PQContext *
00100 pilot_qof_create (void)
00101 {
00102 PQContext *context;
00103 gint name_count;
00104
00105 context = g_new0 (PQContext, 1);
00106 for (name_count = 0; name_count < 16; name_count++)
00107 {
00108 g_sprintf (context->names[name_count], "%s", "");
00109 }
00110 return context;
00111 }
00112
00113 PQContext *
00114 pilot_qof_init (void)
00115 {
00116 qof_init ();
00117 g_return_val_if_fail (AddressRegister (), NULL);
00120 #ifdef HAVE_QOFEXPENSES
00121 g_return_val_if_fail (ExpensesRegister (), NULL);
00122 #endif
00123 g_return_val_if_fail (PQExpensesRegister (), NULL);
00124 g_return_val_if_fail (DateBookRegister (), NULL);
00125 g_return_val_if_fail (ToDoRegister (), NULL);
00126 g_return_val_if_fail (packing_registration(), NULL);
00127 return pilot_qof_create ();
00128 }
00129
00130 typedef enum {
00131 PLU_CAT_NOFLAGS = 0,
00132 PLU_CAT_CASE_INSENSITIVE = 0x0001,
00133 PLU_CAT_DEFAULT_UNFILED = 0x0002,
00134 PLU_CAT_MATCH_NUMBERS = 0x0004,
00135 PLU_CAT_WARN_UNKNOWN = 0x0008
00136 } plu_findcategory_flags_t;
00137
00138
00139 static gint
00140 plu_connect(gchar* plu_port, gint plu_quiet)
00141 {
00142 gint sd = -1;
00143 gint result;
00144
00145 struct SysInfo sys_info;
00146
00147 if (plu_port == NULL)
00148 plu_port = getenv(env_pilotport);
00149 if (plu_port == NULL) {
00150 fprintf (stderr, "\n ");
00151 fprintf (stderr, _("Unable to determine port to bind"));
00152 fprintf (stderr, "\n ");
00153 fprintf (stderr, _("Please use --help for more information"));
00154 fprintf (stderr, "\n\n");
00155 return -1;
00156 }
00157
00158 if ((sd = pi_socket(PI_AF_PILOT,
00159 PI_SOCK_STREAM, PI_PF_DLP)) < 0) {
00160 fprintf(stderr, "\n ");
00161 fprintf(stderr, _("Unable to create socket '%s'"), plu_port);
00162 fprintf(stderr, "\n");
00163 return -1;
00164 }
00165
00166 result = pi_bind(sd, plu_port);
00167
00168 if (result < 0) {
00169 fprintf (stderr, "\n ");
00170 fprintf (stderr, _("Unable to bind to port: %s"), plu_port);;
00171 fprintf (stderr, "\n ");
00172 fprintf (stderr, _("Please use --help for more information"));
00173 fprintf (stderr, "\n\n");
00174 return result;
00175 }
00176
00177 if (!plu_quiet && isatty(fileno(stdout))) {
00178 fprintf (stdout, "\n ");
00179 fprintf (stdout, _("Listening for incoming connection on %s... "),
00180 plu_port);
00181 fflush(stdout);
00182 }
00183
00184 if (pi_listen(sd, 1) < 0) {
00185 fprintf (stderr, "\n ");
00186 fprintf(stderr, _("Error listening on %s"), plu_port);
00187 fprintf (stderr, "\n ");
00188 pi_close(sd);
00189 return -1;
00190 }
00191
00192 sd = pi_accept(sd, 0, 0);
00193 if (sd < 0) {
00194 fprintf (stderr, "\n ");
00195 fprintf(stderr, _("Error accepting data on %s"), plu_port);
00196 fprintf (stderr, "\n ");
00197 pi_close(sd);
00198 return -1;
00199 }
00200
00201 if (!plu_quiet && isatty(fileno(stdout))) {
00202 fprintf(stdout, _("connected!"));
00203 fprintf(stdout, "\n\n");
00204 }
00205
00206 if (dlp_ReadSysInfo(sd, &sys_info) < 0) {
00207 fprintf (stderr, "\n ");
00208 fprintf (stderr, _("Error read system info on %s"), plu_port);
00209 fprintf (stderr, "\n ");
00210 pi_close(sd);
00211 return -1;
00212 }
00213
00214 dlp_OpenConduit(sd);
00215 return sd;
00216 }
00217
00218 static gint
00219 pq_findcategory(PQContext *context, const gchar *name, gint flags)
00220 {
00221 gint cat_index, match_category;
00222
00223 match_category = -1;
00224 for (cat_index = 0; cat_index < 16; cat_index += 1) {
00225 if (context->names[cat_index][0]) {
00226 if (flags & PLU_CAT_CASE_INSENSITIVE) {
00227 if (strncasecmp(context->names[cat_index], name, 15) == 0) {
00228 match_category = cat_index;
00229 break;
00230 }
00231 } else {
00232 if (strncmp(context->names[cat_index],name,15) == 0) {
00233 match_category = cat_index;
00234 break;
00235 }
00236 }
00237 }
00238 }
00239
00240 if ((match_category == -1) && (flags & PLU_CAT_MATCH_NUMBERS)) {
00241 while (isspace(*name)) {
00242 name++;
00243 }
00244 if (isdigit(*name)) {
00245 match_category = atoi(name);
00246 }
00247
00248 if ((match_category < 0) || (match_category > 15)) {
00249 match_category = -1;
00250 }
00251 }
00252
00253 if (flags & PLU_CAT_WARN_UNKNOWN) {
00254 if (match_category == -1) {
00255 fprintf(stderr, _("WARNING: Unknown category '%s'%s.\n"),
00256 name,
00257 (flags & PLU_CAT_DEFAULT_UNFILED) ? _(", using 'Unfiled'") : "");
00258 }
00259 }
00260
00261 if (flags & PLU_CAT_DEFAULT_UNFILED) {
00262 if (match_category == -1) {
00263 match_category = 0;
00264 }
00265 }
00266
00267 return match_category;
00268 }
00269
00270 void
00271 pilot_qof_pack (QofEntity * ent, gpointer user_data)
00272 {
00273 const gchar *category_name;
00274 const QofParam *param;
00275 gint size, result;
00276 QofPack pack_func;
00277 PQContext *context;
00278 const PQPack *p;
00279
00280 context = (PQContext *) user_data;
00281 size = result = 0;
00282 g_return_if_fail (context != NULL);
00283 p = pilot_qof_pack_lookup (ent->e_type);
00284 if (!p)
00285 return;
00286 context->pi_buf = pi_buffer_new (PQ_DEF_BUFSZ);
00287 pack_func = p->pack_func;
00288 if (pack_func == NULL)
00289 {
00290 context->qof.error = TRUE;
00291 return;
00292 }
00293 size = pack_func (ent, context);
00294 if (size == -1)
00295 return;
00296 param = qof_class_get_parameter (ent->e_type, CATEGORY_NAME);
00297 category_name = (const gchar *) param->param_getfcn (ent, param);
00298 context->ent_category = pq_findcategory(context,
00299 category_name, PLU_CAT_CASE_INSENSITIVE | PLU_CAT_DEFAULT_UNFILED);
00300
00301
00302 if (context->ent_category == 0)
00303 PWARN (" Category: '%s' not found or not set, using 'Unfiled'",
00304 category_name);
00305 result = dlp_WriteRecord (context->sd, context->db,
00306 PQ_DLP_REC_ATTR, PQ_DLP_NEW_REC, context->ent_category,
00307 context->pi_buf->data, size, PQ_DLP_SET_ID);
00308 if (result < 0)
00309 {
00310 PERR (" record could not be written: error %d", result);
00311 return;
00312 }
00313 }
00314
00315 void
00316 pilot_qof_unpack (QofEntity * ent, gpointer user_data)
00317 {
00318 QofPack unpack_func;
00319 const PQPack *p;
00320 PQContext *context;
00321 gint result;
00322
00323 context = (PQContext *) user_data;
00324 g_return_if_fail (context && ent);
00325 p = pilot_qof_pack_lookup (ent->e_type);
00326 g_return_if_fail (p);
00327 unpack_func = p->unpack_func;
00328 if (unpack_func == NULL)
00329 {
00330 context->qof.error = TRUE;
00331 PERR ("No unpack routine was defined for the %s object!",
00332 ent->e_type);
00333 return;
00334 }
00335 result = unpack_func (ent, context);
00336 if (result < 0)
00337 {
00338 qof_entity_release (ent);
00339 g_free (ent);
00340 }
00341 }
00342
00343 void
00344 pilot_app_unpack (QofIdTypeConst e_type, gpointer user_data)
00345 {
00346 PQContext *context;
00347 QofPack app_unpack;
00348 const PQPack *p;
00349
00350 context = (PQContext *) user_data;
00351 g_return_if_fail (context != NULL);
00352 p = pilot_qof_pack_lookup (e_type);
00353 if (!p)
00354 return;
00355 app_unpack = p->app_info_unpack;
00356 if (app_unpack == NULL)
00357 {
00358 context->qof.error = TRUE;
00359 PERR (" no app_info_unpack routine for %s", e_type);
00360 return;
00361 }
00362
00363 app_unpack (NULL, context);
00364 }
00365
00366 static void
00367 pilot_entity_free (QofEntity * ent, gpointer user_data)
00368 {
00369 QofPack free_pack_func;
00370 const PQPack *p;
00371
00372 p = pilot_qof_pack_lookup (ent->e_type);
00373 if (!p)
00374 return;
00375 free_pack_func = p->free_pack_func;
00376 free_pack_func (ent, NULL);
00377 }
00378
00379 static void
00380 pilot_object_free (QofObject * obj, gpointer user_data)
00381 {
00382 QofBook *book;
00383
00384 book = (QofBook *) user_data;
00385 qof_object_foreach (obj->e_type, book, pilot_entity_free, NULL);
00386 }
00387
00388 void
00389 pilot_entity_finaliser (QofBook * book, gpointer key, gpointer data)
00390 {
00391 qof_object_foreach_type (pilot_object_free, book);
00392 }
00393
00394 gboolean
00395 pilot_qof_pack_register (const PQPack * p)
00396 {
00397 if (g_list_index (pilot_modules, (gpointer) p) == -1)
00398 pilot_modules = g_list_prepend (pilot_modules, (gpointer) p);
00399 else
00400 return FALSE;
00401 return TRUE;
00402 }
00403
00404 const PQPack *
00405 pilot_qof_pack_lookup (QofIdTypeConst object_type)
00406 {
00407 GList *piter;
00408 PQPack *p;
00409
00410 if (!object_type)
00411 return NULL;
00412 for (piter = pilot_modules; piter; piter = piter->next)
00413 {
00414 p = piter->data;
00415 if (0 == safe_strcmp (p->e_type, object_type))
00416 return p;
00417 }
00418 return NULL;
00419 }
00420
00421 static void
00422 pilot_qof_free (PQContext * data)
00423 {
00424 gint name_count;
00425
00426 for (name_count = 0; name_count < 16; name_count++)
00427 g_sprintf (data->names[name_count], "%s", "");
00428 qof_main_free (&data->qof);
00429 }
00430
00431 static void
00432 write_ent_cb (QofEntity * ent, gpointer user_data)
00433 {
00434 PQContext *context;
00435
00436 context = (PQContext *) user_data;
00437 g_return_if_fail (context && ent);
00438 if (context->qof.error)
00439 return;
00440 context->pi_buf = pi_buffer_new (PQ_DEF_BUFSZ);
00441 pilot_qof_pack (ent, context);
00442 }
00443
00444 static void
00445 pilot_database_open (QofObject * obj, gpointer user_data)
00446 {
00447 gchar *db_name, *log;
00448 PQContext *context;
00449 const PQPack *p;
00450 QofPack pref_unpack;
00451 gint db, attr, category, i, len;
00452 QofBook *book;
00453 QofEntity *ent;
00454 QofInstance *inst;
00455
00456 context = (PQContext *) user_data;
00457 if (context->qof.error)
00458 {
00459 return;
00460 }
00461 pref_unpack = NULL;
00462 len = 0;
00463 i = 0;
00464 p = pilot_qof_pack_lookup (obj->e_type);
00465 if (!p)
00466 return;
00467 db_name = g_strdup (p->palm_db_name);
00468 if (db_name == NULL)
00469 {
00470 context->qof.error = TRUE;
00471 PERR (" object %s has no database name", obj->e_type);
00472 return;
00473 }
00474 if (0 == safe_strcmp (obj->e_type, context->qof.exclude))
00475 return;
00476
00477 if ((context->qof.database != NULL) &&
00478 (0 != safe_strcmp (obj->e_type, context->qof.database)))
00479 return;
00480 if (p->db_pref_unpack)
00481 {
00482 gchar * creator;
00483 gint pref_result = 0;
00484
00485 pref_unpack = p->db_pref_unpack;
00486
00487
00488 creator = g_strdup (p->pref_creator);
00489 pref_result = dlp_ReadAppPreference (context->sd,
00490 makelong (creator), p->pref_flag,
00491 PQ_PREF_USE_BACKUP, PQ_DEF_BUFSZ, context->pref_buf,
00492 PQ_PREF_USE_SIZE, PQ_PREF_VERSION);
00493 pref_unpack (NULL, context);
00494 g_free (creator);
00495 }
00496 if (dlp_OpenDB (context->sd, PQ_DLP_CARD,
00497 PI_DLP_ARG_FLAG_SHORT | PI_DLP_ARG_FLAG_LONG,
00498 db_name, &db) < 0)
00499 {
00500 PWARN (" Unable to open %s database on Palm.\n", db_name);
00501 log =
00502 g_strdup_printf (_
00503 ("%s: Unable to open %s database on Palm.\n"),
00504 PACKAGE, db_name);
00505 dlp_AddSyncLogEntry (context->sd, log);
00506 pi_close (context->sd);
00507 g_free (log);
00508 context->qof.error = TRUE;
00509 return;
00510 }
00511 context->db = db;
00512 context->app_buf = pi_buffer_new (PQ_DEF_BUFSZ);
00513
00514 dlp_ReadAppBlock (context->sd, context->db, PQ_DLP_OFFSET,
00515 PQ_DLP_APPREAD, context->app_buf);
00516 pilot_app_unpack (obj->e_type, context);
00517
00518 if (context->qof.input_file)
00519 {
00520 book = qof_session_get_book (context->qof.input_session);
00521 qof_object_foreach (obj->e_type, book, write_ent_cb, context);
00522 }
00523 context->pi_buf = pi_buffer_new (PQ_DEF_BUFSZ);
00524 book = qof_session_get_book (context->qof.input_session);
00525 for (i = 0; len >= 0; i++)
00526 {
00527 len = dlp_ReadRecordByIndex (context->sd, context->db, i,
00528 context->pi_buf, PQ_DLP_RECORD, &attr, &category);
00529
00530 if ((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
00531 continue;
00532
00533 context->ent_category = category;
00534
00535 inst = (QofInstance *) qof_object_new_instance (obj->e_type, book);
00536 g_return_if_fail (inst != NULL);
00537 ent = &inst->entity;
00538 pilot_qof_unpack (ent, context);
00539 if (context->qof.error == TRUE)
00540 {
00541 len = -1;
00542 break;
00543 }
00544 }
00545 pi_buffer_free (context->app_buf);
00546 pi_buffer_free (context->pi_buf);
00547 g_free (db_name);
00548 dlp_CloseDB (context->sd, context->db);
00549 }
00550
00551 static void
00552 pilot_error (PQContext * context, const gchar * message)
00553 {
00554 PERR (" %s - Error code: %d", message, pi_error(context->sd));
00555 if(context->sd > 0)
00556 {
00557 pi_close(context->sd);
00558 }
00559 qof_session_end(context->qof.input_session);
00560 qof_session_end(context->qof.export_session);
00561 context->qof.error = TRUE;
00562 }
00563
00564 static void
00565 find_invoice_contact (QofEntity * ent, gpointer data)
00566 {
00567 GSList *field_list, *category_param_list;
00568 QofQueryPredData *appt_pred, *exp_pred, *category_pred;
00569 PQContext *context;
00570 const QofParam *param;
00571 const gchar *string;
00572 GList *results;
00573 QofBook *book;
00574
00575 context = (PQContext *) data;
00576 g_return_if_fail (context && ent);
00577 param = NULL;
00578 string = NULL;
00579 results = NULL;
00580 category_param_list = NULL;
00581 if (0 != safe_strcmp (ent->e_type, PILOT_LINK_QOF_EXPENSES)
00582 && (0 != safe_strcmp (ent->e_type, PILOT_LINK_QOF_DATEBOOK)))
00583 return;
00584 ENTER (" ent=%s", ent->e_type);
00585 book = qof_session_get_book (context->qof.input_session);
00586 qof_query_set_book (context->qof.query, book);
00587 field_list = NULL;
00588
00589
00590 if (context->qof.category)
00591 {
00592 category_param_list =
00593 qof_query_build_param_list (CATEGORY_NAME, NULL);
00594 category_pred =
00595 qof_query_string_predicate (QOF_COMPARE_EQUAL,
00596 context->qof.category,
00597 QOF_STRING_MATCH_CASEINSENSITIVE, FALSE);
00598 qof_query_add_term (context->qof.query, category_param_list,
00599 category_pred, QOF_QUERY_AND);
00600 }
00601
00602 if (0 == safe_strcmp (ent->e_type, PILOT_LINK_QOF_EXPENSES))
00603 {
00604 if (context->invoice_vendor)
00605 {
00606 param = qof_class_get_parameter (ent->e_type, EXP_VENDOR);
00607 string = param->param_getfcn (ent, param);
00608 field_list = qof_query_build_param_list (ADDR_CITY, NULL);
00609 }
00610 if (context->invoice_city)
00611 {
00612 param = qof_class_get_parameter (ent->e_type, EXP_CITY);
00613 string = param->param_getfcn (ent, param);
00614 field_list =
00615 qof_query_build_param_list (ADDR_COMPANY, ADDR_TITLE,
00616 NULL);
00617 }
00618 if (string)
00619 {
00620 exp_pred = qof_query_string_predicate (QOF_COMPARE_EQUAL,
00621 string, QOF_STRING_MATCH_CASEINSENSITIVE, FALSE);
00622 qof_query_add_term (context->qof.query, field_list,
00623 exp_pred, QOF_QUERY_AND);
00624 results = qof_query_run (context->qof.query);
00625 if (results != NULL)
00626 qof_entity_copy_list (context->qof.export_session,
00627 results);
00628 }
00629 }
00630 if (0 == safe_strcmp (ent->e_type, PILOT_LINK_QOF_DATEBOOK))
00631 {
00632 param =
00633 qof_class_get_parameter (ent->e_type, DATEBOOK_DESCRIPTION);
00634 string = param->param_getfcn (ent, param);
00635 field_list = qof_query_build_param_list (ADDR_COMPANY,
00636 ADDR_CITY, ADDR_TITLE, NULL);
00637 if (string)
00638 {
00639 appt_pred = qof_query_string_predicate (QOF_COMPARE_EQUAL,
00640 string, QOF_STRING_MATCH_CASEINSENSITIVE, FALSE);
00641 qof_query_add_term (context->qof.query, field_list,
00642 appt_pred, QOF_QUERY_AND);
00643 results = qof_query_run (context->qof.query);
00644 if (results != NULL)
00645 qof_entity_copy_list (context->qof.export_session,
00646 results);
00647 }
00648 }
00649 if (context->qof.query)
00650 qof_query_clear (context->qof.query);
00651 LEAVE (" ");
00652 }
00653
00654 static void
00655 check_invoice_handler (PQContext * context)
00656 {
00657 if (!context->qof.min_qt)
00658 {
00659 fprintf (stderr, _("%s: Error: Please specify a time period "
00660 "using -t."), PACKAGE);
00661 fprintf (stderr, "\n\n");
00662 qof_session_end (context->qof.input_session);
00663 context->qof.error = TRUE;
00664 return;
00665 }
00666 if (context->qof.exclude)
00667 {
00668 g_free (context->qof.exclude);
00669 context->qof.exclude = NULL;
00670 }
00671 context->qof.exclude = g_strdup (PILOT_LINK_QOF_TODO);
00672 if (context->qof.database)
00673 {
00674 g_free (context->qof.database);
00675 context->qof.database = NULL;
00676 }
00677 if (context->qof.input_file)
00678 {
00679 g_free (context->qof.input_file);
00680 context->qof.input_file = NULL;
00681 }
00682 if (context->qof.sql_str)
00683 {
00684 g_free (context->qof.sql_str);
00685 context->qof.sql_str = NULL;
00686 }
00687 if (context->qof.sql_list)
00688 {
00689 g_list_free (context->qof.sql_list);
00690 context->qof.sql_list = NULL;
00691 }
00692 }
00693
00694 void
00695 qof_cmd_hotsync (PQContext * context)
00696 {
00697 struct PilotUser QUser;
00698 QofBook *book;
00699 gchar *log_msg;
00700
00701 if (0 == safe_strcmp (context->qof.exclude, context->qof.database)
00702 && (context->qof.exclude != NULL))
00703 {
00704
00705
00706 qof_main_wrap_line (stderr, ERR_INDENT,
00707 _("%s: Error: Cannot exclude "
00708 "database \"%s\" with option -e because option -d is set to the "
00709 "same database: \"%s\""), PACKAGE, context->qof.exclude,
00710 context->qof.database);
00711 qof_session_end (context->qof.input_session);
00712 return;
00713 }
00714 if ((context->invoice_city) || (context->invoice_vendor))
00715 check_invoice_handler (context);
00716 if (context->qof.error)
00717 return;
00718 if (context->qof.input_file)
00719 {
00720 PINFO (" Trying to upload %s", context->qof.input_file);
00721 qof_session_begin (context->qof.input_session,
00722 context->qof.input_file, TRUE, FALSE);
00723 qof_session_load (context->qof.input_session, NULL);
00724 }
00725 else
00726 qof_session_begin (context->qof.input_session, QOF_STDOUT, TRUE,
00727 FALSE);
00728 context->qof.export_session = qof_session_new ();
00729
00730 context->sd = plu_connect (context->port, context->quiet);
00731
00732 if (context->sd < 0)
00733 {
00734 pilot_error (context, _("Unable to connect to the Palm"));
00735 return;
00736 }
00737 if (dlp_ReadUserInfo (context->sd, &QUser) < 0)
00738 {
00739 pilot_error (context, _("Unable to read Palm user info"));
00740 return;
00741 }
00742 context->qof.error = FALSE;
00743 qof_object_foreach_type (pilot_database_open, context);
00744 QUser.lastSyncPC = 0x00010000;
00745 QUser.lastSyncDate = QUser.successfulSyncDate = time (0);
00746 if (dlp_WriteUserInfo (context->sd, &QUser) < 0)
00747 {
00748 pilot_error (context, _("Unable to write user info"));
00749 return;
00750 }
00751
00752 log_msg = g_strdup_printf (_("%s hotsync\n\n"
00753 "Thank you for using %s.\n"), PACKAGE, PACKAGE);
00754 dlp_AddSyncLogEntry (context->sd, log_msg);
00755 g_free (log_msg);
00756 dlp_EndOfSync (context->sd, 0);
00757 pi_close (context->sd);
00758
00759
00760 if (context->qof.write_file)
00761 {
00762 qof_session_begin (context->qof.export_session,
00763 context->qof.write_file, TRUE, TRUE);
00764 qof_mod_compression (context->qof.gz_level, &context->qof);
00765 }
00766 else
00767 qof_session_begin (context->qof.export_session, QOF_STDOUT, TRUE,
00768 FALSE);
00769
00770
00771
00772
00773
00774
00775 qof_main_moderate_query (&context->qof);
00776
00777 if ((context->invoice_city) || (context->invoice_vendor))
00778 {
00779 book = qof_session_get_book (context->qof.export_session);
00780 context->qof.query = qof_query_create_for (PILOT_LINK_QOF_ADDRESS);
00781 qof_object_foreach (PILOT_LINK_QOF_DATEBOOK, book,
00782 find_invoice_contact, context);
00783 qof_object_foreach (PILOT_LINK_QOF_EXPENSES, book,
00784 find_invoice_contact, context);
00785 }
00786 qof_session_save (context->qof.export_session, NULL);
00787 qof_main_show_error (context->qof.export_session);
00788 qof_session_end (context->qof.input_session);
00789 qof_session_end (context->qof.export_session);
00790 }
00791
00792 static void
00793 pq_invoice_xmlfile (PQContext * context)
00794 {
00795 QofBook *book;
00796
00797 ENTER (" ");
00798 qof_session_begin (context->qof.input_session, context->qof.filename,
00799 TRUE, FALSE);
00800 qof_session_load (context->qof.input_session, NULL);
00801 context->qof.export_session = qof_session_new ();
00802 if (context->qof.write_file)
00803 {
00804 qof_session_begin (context->qof.export_session,
00805 context->qof.write_file, TRUE, TRUE);
00806 qof_mod_compression (context->qof.gz_level, &context->qof);
00807 }
00808 else
00809 qof_session_begin (context->qof.export_session, QOF_STDOUT,
00810 TRUE, TRUE);
00811 qof_main_moderate_query (&context->qof);
00812 book = qof_session_get_book (context->qof.export_session);
00813 context->qof.query = qof_query_create_for (PILOT_LINK_QOF_ADDRESS);
00814 qof_object_foreach (PILOT_LINK_QOF_DATEBOOK, book,
00815 find_invoice_contact, context);
00816 qof_object_foreach (PILOT_LINK_QOF_EXPENSES, book,
00817 find_invoice_contact, context);
00818 qof_session_save (context->qof.export_session, NULL);
00819 qof_main_show_error (context->qof.export_session);
00820 qof_main_show_error (context->qof.input_session);
00821 qof_session_end (context->qof.input_session);
00822 qof_session_end (context->qof.export_session);
00823 LEAVE (" ");
00824 }
00825
00826 int
00827 main (int argc, const char *argv[])
00828 {
00829 const gchar *help_header_text, *input_file, *plu_port;
00830 gint plu_quiet, optc;
00831 PQContext *pilot_qof_context;
00832 gboolean debug_on;
00833 poptContext pc;
00834 gint64 gz_level;
00835 qof_op_type palm_command;
00836
00837 QOF_OP_VARS struct poptOption options[] = {
00838 {"port", 'p', POPT_ARG_STRING, &plu_port, 0,
00839 _("Use the device <port> to communicate with Palm"),
00840 "<port>"},
00841 { "quiet", 'q', POPT_ARG_NONE, &plu_quiet, 0 ,
00842 _("Suppress HotSync connection messages"), NULL},
00843 {"input-file", 'i', POPT_ARG_STRING, &filename, qof_op_offline,
00844 _("Query the data in <filename>"), _("filename")},
00845 QOF_CLI_OPTIONS
00846 {"hot-query", 'a', POPT_ARG_NONE,
00847 NULL, qof_op_hotsync,
00848 _("Activate/HotSync and query the Palm."), NULL},
00849 {"upload", 'u', POPT_ARG_STRING, &input_file, qof_op_upload,
00850 _("Upload data from <filename> to the Palm. Requires -a"),
00851 "filename"},
00852 {"invoice-vendor", 0, POPT_ARG_NONE, NULL, qof_op_inv_vendor,
00853 _
00854 ("Shorthand to relate an event or expense to a contact, by vendor. "
00855 "Requires -t."), NULL},
00856 {"invoice-city", 0, POPT_ARG_NONE, NULL, qof_op_inv_city,
00857 _
00858 ("Shorthand to relate an event or expense to a contact, by city. "
00859 "Requires -t."), NULL},
00860 {"use-locale", 0, POPT_ARG_NONE, NULL, qof_op_use_locale,
00861 _
00862 ("Write XML using the current locale encoding instead of UTF-8."),
00863 NULL},
00864 POPT_TABLEEND
00865 };
00866
00867 palm_command = qof_op_noop;
00868 debug_on = FALSE;
00869 QOF_OP_INIT;
00870 input_file = NULL;
00871 plu_quiet = 0;
00872 plu_port = NULL;
00873
00874 #ifdef ENABLE_NLS
00875 setlocale (LC_ALL, "");
00876 bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
00877 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00878 textdomain (GETTEXT_PACKAGE);
00879 #endif
00880
00881 help_header_text = _("\n"
00882 " Query Palm databases as objects and save to XML.\n"
00883
00884 " pilot-qof provides a query interface to data on a Palm device,\n"
00885 " using pilot-link and QOF - the Query Object Framework.\n\n"
00886 " pilot-qof supports reading addressbook, datebook, expenses and\n"
00887 " ToDo data from a Palm device to XML files. pilot-qof runs SQL-type\n"
00888 " queries on the live data or a QSF XML file and results can be imported\n"
00889 " into other QOF applications or converted to other text based formats,\n"
00890 " including non-XML formats like vcard.\n"
00891 " See http://pilot-qof.sourceforge.net/\n\n"
00892 " Commands are -x -a -l --explain -s or -f.\n"
00893 " Options are -c -t -w, -d or -e.\n"
00894 " option -u requires -a\n\n");
00895
00896 pc = poptGetContext (PACKAGE, argc, argv, options, 0);
00897
00898 poptSetOtherOptionHelp (pc, help_header_text);
00899
00900 if (argc < 2)
00901 {
00902 poptPrintUsage (pc, stderr, 0);
00903 return EXIT_FAILURE;
00904 }
00905 pilot_qof_context = pilot_qof_init ();
00906 if (!pilot_qof_context)
00907 {
00908 qof_main_wrap_line (stderr, ERR_INDENT,
00909 _("%s: Failed to initialise "
00910 "the query object framework."), PACKAGE);
00911 return EXIT_FAILURE;
00912 }
00913
00914
00915 qof_mod_convert_deprecated (1, &pilot_qof_context->qof);
00916 while ((optc = poptGetNextOpt (pc)) >= 0)
00917 {
00918 switch (optc)
00919 {
00920
00921 case qof_op_offline:
00922 case qof_op_list:
00923 case qof_op_explain:
00924 case qof_op_hotsync:
00925 {
00926 palm_command = optc;
00927 break;
00928 }
00929 case qof_op_sql:
00930 {
00931 qof_mod_sql (sql_query, &pilot_qof_context->qof);
00932 if (!filename)
00933 {
00934 filename = g_strdup (QOF_STDOUT);
00935 }
00936 palm_command = qof_op_empty;
00937 break;
00938 }
00939 case qof_op_sql_file:
00940 {
00941 qof_mod_sql_file (sql_file, &pilot_qof_context->qof);
00942 palm_command = qof_op_empty;
00943 break;
00944 }
00945 case qof_op_vers:
00946 {
00947 fprintf (stdout, _("\n This is %s v%s\n"), PACKAGE,
00948 VERSION);
00949 fprintf (stdout,
00950 _
00951 (" Query interface for Palm databases as objects.\n"));
00952 fprintf (stdout,
00953 "\n Copyright (c) 2005-2006 "
00954 "Neil Williams <linux@codehelp.co.uk>\n");
00955 fprintf (stdout,
00956 _(" For %s support, join the QOF-devel "
00957 "mailing list at\n"), PACKAGE);
00958 fprintf (stdout,
00959 " http://lists.sourceforge.net/mailman/listinfo/qof-devel\n\n");
00960
00961 fprintf (stdout, _(" Build target............: %s\n"),
00962 HOST_OS);
00963
00964 fprintf (stdout, _(" Build date..............: %s %s\n"),
00965 __DATE__, __TIME__);
00966
00967 fprintf (stdout, _(" Built for pilot-link ...: %s\n"),
00968 PILOT_LINK_SUPPORT);
00969
00970 fprintf (stdout, _(" --debug logs to.........: %s/%s\n\n"),
00971 g_get_tmp_dir (), PILOT_QOF_LOG);
00972 fprintf (stdout,
00973 _
00974 (" Please use --help for more detailed options.\n\n"));
00975 return EXIT_SUCCESS;
00976 }
00977
00978 case qof_op_category:
00979 {
00980 qof_mod_category (category, &pilot_qof_context->qof);
00981 break;
00982 }
00983 case qof_op_database:
00984 {
00985 qof_mod_database (database, &pilot_qof_context->qof);
00986 break;
00987 }
00988 case qof_op_time:
00989 {
00990 qof_mod_time (date_time, &pilot_qof_context->qof);
00991 break;
00992 }
00993 case qof_op_exclude:
00994 {
00995 qof_mod_exclude (exclude, &pilot_qof_context->qof);
00996 break;
00997 }
00998 case qof_op_write:
00999 {
01000 qof_mod_write (write_file, &pilot_qof_context->qof);
01001 break;
01002 }
01003 case qof_op_upload:
01004 {
01005 if (palm_command != qof_op_hotsync)
01006 {
01007 fprintf (stderr,
01008 _("%s: Error: Please specify -a if you use -u\n"),
01009 PACKAGE);
01010 poptPrintUsage (pc, stderr, 0);
01011 return EXIT_FAILURE;
01012 }
01013 pilot_qof_context->qof.input_file = g_strdup (input_file);
01014 break;
01015 }
01016 case qof_op_debug:
01017 {
01018 gchar *log;
01019
01020 log =
01021 g_strconcat (g_get_tmp_dir (), "/", PILOT_QOF_LOG,
01022 NULL);
01023 qof_log_init_filename (log);
01024 g_free (log);
01025 qof_log_set_default (QOF_LOG_DETAIL);
01026 qof_log_set_level (PQ_MOD_CLI, QOF_LOG_DETAIL);
01027 qof_log_set_level (PQ_MOD_PILOT, QOF_LOG_DETAIL);
01028 qof_log_set_level (QOF_MAIN_CLI, QOF_LOG_DETAIL);
01029 qof_log_set_level (QOF_MOD_QSF, QOF_LOG_DETAIL);
01030 qof_log_set_level ("qof-sqlite-module", QOF_LOG_DETAIL);
01031 debug_on = TRUE;
01033 break;
01034 }
01035 case qof_op_compress:
01036 {
01037 pilot_qof_context->qof.gz_level = gz_level;
01038 break;
01039 }
01040 case qof_op_inv_vendor:
01041 {
01042 if (!pilot_qof_context->invoice_city)
01043 pilot_qof_context->invoice_vendor = TRUE;
01044 break;
01045 }
01046 case qof_op_inv_city:
01047 {
01048 pilot_qof_context->invoice_city = TRUE;
01049 pilot_qof_context->invoice_vendor = FALSE;
01050 break;
01051 }
01052 case qof_op_use_locale:
01053 {
01054 const gchar *locale_encoding;
01055 gboolean test;
01056 locale_encoding = NULL;
01057 test = g_get_charset (&locale_encoding);
01058 if (!test)
01059 qof_mod_encoding (locale_encoding,
01060 &pilot_qof_context->qof);
01061 break;
01062 }
01063 default:
01064 {
01065 fprintf (stderr, _("%s: ERROR: got option %d, arg %s\n"),
01066 PACKAGE, optc, poptGetOptArg (pc));
01067 return EXIT_FAILURE;
01068 }
01069 }
01070 }
01071 if (qof_op_noop == palm_command)
01072 {
01073 qof_main_wrap_line (stderr, ERR_INDENT,
01074 _("%s: ERROR: specify a command "
01075 "-x, -a, -l, -s or -f, or --explain.\n"), PACKAGE);
01076 poptPrintUsage (pc, stderr, 0);
01077 return EXIT_FAILURE;
01078 }
01079 if (qof_op_noop == palm_command)
01080 {
01081 fprintf (stderr, _("%s: ERROR: specify a command "
01082 "-x, -a, -l, -s or -f, or --explain.\n"), PACKAGE);
01083 poptPrintUsage(pc, stderr, 0);
01084 return EXIT_FAILURE;
01085 }
01086 if (optc < -1)
01087 {
01088 fprintf (stderr, "%s: %s %s\n\n", PACKAGE,
01089 poptBadOption (pc, POPT_BADOPTION_NOALIAS),
01090 poptStrerror (optc));
01091 poptPrintUsage (pc, stderr, 0);
01092 return EXIT_FAILURE;
01093 }
01094
01095 pilot_qof_context->qof.input_session = qof_session_new ();
01096 switch (palm_command)
01097 {
01098 case qof_op_empty:
01099 {
01100 pilot_qof_context->qof.filename = g_strdup (filename);
01101 if ((pilot_qof_context->invoice_city)
01102 || (pilot_qof_context->invoice_vendor))
01103 {
01104 check_invoice_handler (pilot_qof_context);
01105 if (pilot_qof_context->qof.error)
01106 return EXIT_FAILURE;
01107 pq_invoice_xmlfile (pilot_qof_context);
01108 }
01109 else
01110 qof_cmd_xmlfile (&pilot_qof_context->qof);
01111 break;
01112 }
01113 case qof_op_offline:
01114 {
01115 pilot_qof_context->qof.filename = g_strdup (filename);
01116 if ((pilot_qof_context->invoice_city)
01117 || (pilot_qof_context->invoice_vendor))
01118 {
01119 check_invoice_handler (pilot_qof_context);
01120 if (pilot_qof_context->qof.error)
01121 return EXIT_FAILURE;
01122 pq_invoice_xmlfile (pilot_qof_context);
01123 }
01124 else
01125 qof_cmd_xmlfile (&pilot_qof_context->qof);
01126 break;
01127 }
01128 case qof_op_list:
01129 {
01130 DEBUG (" list mode");
01131 qof_cmd_list ();
01132 break;
01133 }
01134 case qof_op_explain:
01135 {
01136 if (!pilot_qof_context->qof.database)
01137 {
01138 qof_main_wrap_line (stderr, ERR_INDENT,
01139 _("%s: Error: please specify which database "
01140 "you would like explained.\n\n"), PACKAGE);
01141 break;
01142 }
01143 DEBUG (" explain mode");
01144 qof_cmd_explain (&pilot_qof_context->qof);
01145 break;
01146 }
01147 case qof_op_hotsync:
01148 {
01149 DEBUG (" hotsync mode");
01150 pilot_qof_context->port = g_strdup (plu_port);
01151 pilot_qof_context->quiet = plu_quiet;
01152 qof_cmd_hotsync (pilot_qof_context);
01153 break;
01154 }
01155 case qof_op_noop:
01156 case qof_op_category:
01157 case qof_op_database:
01158 case qof_op_time:
01159 case qof_op_exclude:
01160 case qof_op_sql:
01161 case qof_op_sql_file:
01162 case qof_op_write:
01163 case qof_op_upload:
01164 case qof_op_vers:
01165 case qof_op_compress:
01166 case qof_op_debug:
01167 case qof_op_inv_city:
01168 case qof_op_inv_vendor:
01169 case qof_op_use_locale:
01170 default:
01171 break;
01172 }
01173 poptFreeContext (pc);
01174 pilot_qof_free (pilot_qof_context);
01175 if (debug_on)
01176 qof_log_shutdown ();
01177 qof_close ();
01178 return EXIT_SUCCESS;
01179 }
01180