| | 394 | /* |
|---|
| | 395 | * Fetch notes from disk (from the notes subdirectory of localdir) |
|---|
| | 396 | */ |
|---|
| | 397 | gboolean local_fetch_notes(OpiePluginEnv* env, xmlDoc *doc, const char *tempsourcepath) |
|---|
| | 398 | { |
|---|
| | 399 | osync_trace(TRACE_ENTRY, "%s(%p, %p, %s)", __func__, env, doc, tempsourcepath); |
|---|
| | 400 | gboolean rc = TRUE; |
|---|
| | 401 | char *notesdir = NULL; |
|---|
| | 402 | |
|---|
| | 403 | if(tempsourcepath) { |
|---|
| | 404 | notesdir = g_strdup(tempsourcepath); |
|---|
| | 405 | } |
|---|
| | 406 | else { |
|---|
| | 407 | notesdir = g_build_filename(env->localdir, "notes", NULL); |
|---|
| | 408 | if(g_mkdir_with_parents(notesdir, 0700)) { |
|---|
| | 409 | osync_trace(TRACE_EXIT_ERROR, "%s: failed to create path %s: %s", __func__, notesdir, strerror(errno)); |
|---|
| | 410 | g_free(notesdir); |
|---|
| | 411 | return FALSE; |
|---|
| | 412 | } |
|---|
| | 413 | } |
|---|
| | 414 | |
|---|
| | 415 | GError *gerror = NULL; |
|---|
| | 416 | GDir *dir = g_dir_open(notesdir, 0, &gerror); |
|---|
| | 417 | if(!dir) { |
|---|
| | 418 | osync_trace(TRACE_EXIT_ERROR, "%s: failed to open local directory %s: %s", __func__, notesdir, gerror->message); |
|---|
| | 419 | g_free(notesdir); |
|---|
| | 420 | return FALSE; |
|---|
| | 421 | } |
|---|
| | 422 | else { |
|---|
| | 423 | GPatternSpec *pspec = g_pattern_spec_new("*.txt"); |
|---|
| | 424 | while(TRUE) { |
|---|
| | 425 | const char *localfile = g_dir_read_name(dir); |
|---|
| | 426 | if(!localfile) |
|---|
| | 427 | break; |
|---|
| | 428 | |
|---|
| | 429 | if(g_pattern_match_string(pspec, localfile)) { |
|---|
| | 430 | char *localpath = g_build_filename(notesdir, localfile, NULL); |
|---|
| | 431 | int len = 0; |
|---|
| | 432 | char *str = NULL; |
|---|
| | 433 | OSyncError *error = NULL; |
|---|
| | 434 | rc = osync_file_read(localpath, &str, &len, &error); |
|---|
| | 435 | g_free(localpath); |
|---|
| | 436 | if(rc) { |
|---|
| | 437 | /* FIXME this is probably not correct for calling opie_xml_add_note_node() */ |
|---|
| | 438 | char *filename = g_strdup(localfile); |
|---|
| | 439 | int namelen = strlen(filename); |
|---|
| | 440 | if(namelen > 4) |
|---|
| | 441 | filename[namelen-4] = 0; |
|---|
| | 442 | |
|---|
| | 443 | opie_xml_add_note_node(doc, filename, filename, str); |
|---|
| | 444 | g_free(filename); |
|---|
| | 445 | g_free(str); |
|---|
| | 446 | } |
|---|
| | 447 | else { |
|---|
| | 448 | osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); |
|---|
| | 449 | g_dir_close(dir); |
|---|
| | 450 | g_free(notesdir); |
|---|
| | 451 | g_pattern_spec_free(pspec); |
|---|
| | 452 | return FALSE; |
|---|
| | 453 | } |
|---|
| | 454 | } |
|---|
| | 455 | } |
|---|
| | 456 | g_pattern_spec_free(pspec); |
|---|
| | 457 | } |
|---|
| | 458 | g_dir_close(dir); |
|---|
| | 459 | |
|---|
| | 460 | g_free(notesdir); |
|---|
| | 461 | |
|---|
| | 462 | osync_trace(TRACE_EXIT, "%s(%i)", __func__, rc ); |
|---|
| | 463 | return rc; |
|---|
| | 464 | } |
|---|
| | 465 | |
|---|
| | 466 | /* |
|---|
| | 467 | * Write note changes to disk (into the notes subdirectory of localdir) |
|---|
| | 468 | */ |
|---|
| | 469 | gboolean local_put_notes(OpiePluginEnv* env, xmlDoc *doc, const char *tempdestpath, gboolean delete_files) |
|---|
| | 470 | { |
|---|
| | 471 | osync_trace(TRACE_ENTRY, "%s(%p, %p, %s, %i)", __func__, env, doc, tempdestpath, delete_files); |
|---|
| | 472 | gboolean rc = TRUE; |
|---|
| | 473 | char *notesdir = NULL; |
|---|
| | 474 | |
|---|
| | 475 | if(tempdestpath) { |
|---|
| | 476 | notesdir = g_strdup(tempdestpath); |
|---|
| | 477 | } |
|---|
| | 478 | else { |
|---|
| | 479 | notesdir = g_build_filename(env->localdir, "notes", NULL); |
|---|
| | 480 | if(g_mkdir_with_parents(notesdir, 0700)) { |
|---|
| | 481 | osync_trace(TRACE_EXIT_ERROR, "%s: failed to create local path %s: %s", __func__, notesdir, strerror(errno)); |
|---|
| | 482 | g_free(notesdir); |
|---|
| | 483 | return FALSE; |
|---|
| | 484 | } |
|---|
| | 485 | } |
|---|
| | 486 | |
|---|
| | 487 | xmlNode *node = opie_xml_get_first(doc, "notes", "note"); |
|---|
| | 488 | while(node) { |
|---|
| | 489 | char *changedflag = xmlGetProp(node, "changed"); |
|---|
| | 490 | if(changedflag) { |
|---|
| | 491 | xmlFree(changedflag); |
|---|
| | 492 | |
|---|
| | 493 | char *notename = xmlGetProp(node, "name"); |
|---|
| | 494 | if(notename) { |
|---|
| | 495 | char *notefile = g_strdup_printf("%s.txt", notename); |
|---|
| | 496 | char *notepath = g_build_filename(notesdir, notefile, NULL); |
|---|
| | 497 | g_free(notefile); |
|---|
| | 498 | |
|---|
| | 499 | char *deletedflag = xmlGetProp(node, "deleted"); |
|---|
| | 500 | if(deletedflag) { |
|---|
| | 501 | /* This note has been marked deleted, so delete it */ |
|---|
| | 502 | xmlFree(deletedflag); |
|---|
| | 503 | |
|---|
| | 504 | if(delete_files) { |
|---|
| | 505 | if(g_unlink(notepath)) { |
|---|
| | 506 | osync_trace(TRACE_EXIT_ERROR, "%s: failed to create local path %s: %s", __func__, notesdir, strerror(errno)); |
|---|
| | 507 | g_free(notesdir); |
|---|
| | 508 | xmlFree(notename); |
|---|
| | 509 | return FALSE; |
|---|
| | 510 | } |
|---|
| | 511 | } |
|---|
| | 512 | } |
|---|
| | 513 | else { |
|---|
| | 514 | /* Changed note, write it */ |
|---|
| | 515 | char *content = xmlNodeGetContent(node); |
|---|
| | 516 | if(content) { |
|---|
| | 517 | OSyncError *error = NULL; |
|---|
| | 518 | osync_bool rc = osync_file_write(notepath, content, strlen(content), 0660, &error); |
|---|
| | 519 | xmlFree(content); |
|---|
| | 520 | if(!rc) { |
|---|
| | 521 | osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); |
|---|
| | 522 | g_free(notepath); |
|---|
| | 523 | g_free(notesdir); |
|---|
| | 524 | xmlFree(notename); |
|---|
| | 525 | return FALSE; |
|---|
| | 526 | } |
|---|
| | 527 | } |
|---|
| | 528 | } |
|---|
| | 529 | |
|---|
| | 530 | g_free(notepath); |
|---|
| | 531 | xmlFree(notename); |
|---|
| | 532 | } |
|---|
| | 533 | } |
|---|
| | 534 | node = opie_xml_get_next(node); |
|---|
| | 535 | } |
|---|
| | 536 | |
|---|
| | 537 | g_free(notesdir); |
|---|
| | 538 | |
|---|
| | 539 | osync_trace(TRACE_EXIT, "%s(%i)", __func__, rc ); |
|---|
| | 540 | return TRUE; |
|---|
| | 541 | } |
|---|
| | 542 | |
|---|
| | 1224 | |
|---|
| | 1225 | /* |
|---|
| | 1226 | * scp_fetch_notes |
|---|
| | 1227 | */ |
|---|
| | 1228 | gboolean scp_fetch_notes(OpiePluginEnv* env, xmlDoc *doc) |
|---|
| | 1229 | { |
|---|
| | 1230 | osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, doc); |
|---|
| | 1231 | |
|---|
| | 1232 | gboolean rc = TRUE; |
|---|
| | 1233 | char* scpcommand = NULL; |
|---|
| | 1234 | int scpretval, scpexitstatus; |
|---|
| | 1235 | |
|---|
| | 1236 | if(env->url && env->device_port && env->username) { |
|---|
| | 1237 | char* separator_path; |
|---|
| | 1238 | if ( env->use_qcop ) |
|---|
| | 1239 | { |
|---|
| | 1240 | char* root_path = qcop_get_root(env->qcopconn); |
|---|
| | 1241 | if(!root_path) { |
|---|
| | 1242 | fprintf(stderr, "qcop_get_root: %s\n", env->qcopconn->resultmsg); |
|---|
| | 1243 | osync_trace(TRACE_EXIT_ERROR, "qcop_get_root: %s", env->qcopconn->resultmsg); |
|---|
| | 1244 | return FALSE; |
|---|
| | 1245 | } |
|---|
| | 1246 | osync_trace( TRACE_INTERNAL, "QCop root path = %s", root_path ); |
|---|
| | 1247 | separator_path = g_strdup_printf("%s/", root_path); |
|---|
| | 1248 | g_free(root_path); |
|---|
| | 1249 | } else { |
|---|
| | 1250 | separator_path = g_strdup( "/" ); |
|---|
| | 1251 | } |
|---|
| | 1252 | |
|---|
| | 1253 | /* Create a temp directory */ |
|---|
| | 1254 | char *randstr = g_strdup_printf("opie-sync-%i", g_random_int_range(0, G_MAXUINT32)); |
|---|
| | 1255 | char *temppath = g_build_filename(g_get_tmp_dir(), randstr); |
|---|
| | 1256 | g_free(randstr); |
|---|
| | 1257 | |
|---|
| | 1258 | if(g_mkdir(temppath, 0700)) { |
|---|
| | 1259 | /* Create failed */ |
|---|
| | 1260 | osync_trace(TRACE_INTERNAL, "failed to create temp dir %s: %s", temppath, strerror(errno)); |
|---|
| | 1261 | g_free(temppath); |
|---|
| | 1262 | goto error; |
|---|
| | 1263 | } |
|---|
| | 1264 | |
|---|
| | 1265 | /* A crude test to see if files exist. You can't combine |
|---|
| | 1266 | this with scp unfortunately because scp seems to return 1 |
|---|
| | 1267 | on any error */ |
|---|
| | 1268 | scpcommand = g_strdup_printf("ssh -o BatchMode=yes %s@%s \"ls %s*.txt > /dev/null\"", |
|---|
| | 1269 | env->username, |
|---|
| | 1270 | env->url, |
|---|
| | 1271 | separator_path); |
|---|
| | 1272 | |
|---|
| | 1273 | scpretval = pclose(popen(scpcommand,"w")); |
|---|
| | 1274 | scpexitstatus = WEXITSTATUS(scpretval); |
|---|
| | 1275 | |
|---|
| | 1276 | if(scpexitstatus != 1) { |
|---|
| | 1277 | if((scpretval == -1) || (scpexitstatus != 0)) { |
|---|
| | 1278 | rc = FALSE; |
|---|
| | 1279 | osync_trace( TRACE_INTERNAL, "ssh login failed" ); |
|---|
| | 1280 | goto error; |
|---|
| | 1281 | } |
|---|
| | 1282 | g_free(scpcommand); |
|---|
| | 1283 | |
|---|
| | 1284 | /* Fetch all text files from the remote path into the temp directory */ |
|---|
| | 1285 | scpcommand = g_strdup_printf("scp -p -q -B %s@%s:%s*.txt %s", |
|---|
| | 1286 | env->username, |
|---|
| | 1287 | env->url, |
|---|
| | 1288 | separator_path, |
|---|
| | 1289 | temppath); |
|---|
| | 1290 | |
|---|
| | 1291 | scpretval = pclose(popen(scpcommand,"w")); |
|---|
| | 1292 | scpexitstatus = WEXITSTATUS(scpretval); |
|---|
| | 1293 | |
|---|
| | 1294 | if((scpretval == -1) || (scpexitstatus != 0)) { |
|---|
| | 1295 | osync_trace( TRACE_INTERNAL, "scp transfer failed" ); |
|---|
| | 1296 | rc = FALSE; |
|---|
| | 1297 | goto error; |
|---|
| | 1298 | } |
|---|
| | 1299 | else { |
|---|
| | 1300 | osync_trace( TRACE_INTERNAL, "scp ok" ); |
|---|
| | 1301 | } |
|---|
| | 1302 | |
|---|
| | 1303 | /* Now fetch the docs from the local temp dir */ |
|---|
| | 1304 | rc = local_fetch_notes(env, doc, temppath); |
|---|
| | 1305 | } |
|---|
| | 1306 | |
|---|
| | 1307 | /* Delete temp dir (regardless of whether preceding code succeeded) */ |
|---|
| | 1308 | if(!delete_directory(temppath)) |
|---|
| | 1309 | rc = FALSE; |
|---|
| | 1310 | g_free(temppath); |
|---|
| | 1311 | } |
|---|
| | 1312 | |
|---|
| | 1313 | error: |
|---|
| | 1314 | |
|---|
| | 1315 | if(scpcommand); |
|---|
| | 1316 | g_free(scpcommand); |
|---|
| | 1317 | |
|---|
| | 1318 | osync_trace(TRACE_EXIT, "%s(%i)", __func__, rc ); |
|---|
| | 1319 | return rc; |
|---|
| | 1320 | } |
|---|
| | 1321 | |
|---|
| | 1322 | /* |
|---|
| | 1323 | * scp_put_notes |
|---|
| | 1324 | */ |
|---|
| | 1325 | gboolean scp_put_notes(OpiePluginEnv* env, xmlDoc *doc) |
|---|
| | 1326 | { |
|---|
| | 1327 | osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, doc); |
|---|
| | 1328 | |
|---|
| | 1329 | gboolean rc = TRUE; |
|---|
| | 1330 | char* scpcommand = NULL; |
|---|
| | 1331 | int scpretval, scpexitstatus; |
|---|
| | 1332 | char *temppath = NULL; |
|---|
| | 1333 | char *separator_path = NULL; |
|---|
| | 1334 | |
|---|
| | 1335 | if(env->url && env->device_port && env->username) { |
|---|
| | 1336 | if ( env->use_qcop ) |
|---|
| | 1337 | { |
|---|
| | 1338 | char* root_path = qcop_get_root(env->qcopconn); |
|---|
| | 1339 | if(!root_path) { |
|---|
| | 1340 | fprintf(stderr, "qcop_get_root: %s\n", env->qcopconn->resultmsg); |
|---|
| | 1341 | osync_trace(TRACE_EXIT_ERROR, "qcop_get_root: %s", env->qcopconn->resultmsg); |
|---|
| | 1342 | return FALSE; |
|---|
| | 1343 | } |
|---|
| | 1344 | osync_trace( TRACE_INTERNAL, "QCop root path = %s", root_path ); |
|---|
| | 1345 | separator_path = g_strdup_printf("%s/", root_path); |
|---|
| | 1346 | g_free(root_path); |
|---|
| | 1347 | } else { |
|---|
| | 1348 | separator_path = g_strdup( "/" ); |
|---|
| | 1349 | } |
|---|
| | 1350 | |
|---|
| | 1351 | /* Create a temp directory */ |
|---|
| | 1352 | char *randstr = g_strdup_printf("opie-sync-%i", g_random_int_range(0, G_MAXUINT32)); |
|---|
| | 1353 | temppath = g_build_filename(g_get_tmp_dir(), randstr); |
|---|
| | 1354 | g_free(randstr); |
|---|
| | 1355 | |
|---|
| | 1356 | if(g_mkdir(temppath, 0700)) { |
|---|
| | 1357 | /* Create failed */ |
|---|
| | 1358 | osync_trace(TRACE_INTERNAL, "failed to create temp dir %s: %s", temppath, strerror(errno)); |
|---|
| | 1359 | goto error; |
|---|
| | 1360 | } |
|---|
| | 1361 | |
|---|
| | 1362 | /* Write notes to temp dir */ |
|---|
| | 1363 | rc = local_put_notes(env, doc, temppath, FALSE); |
|---|
| | 1364 | if(!rc) { |
|---|
| | 1365 | osync_trace(TRACE_INTERNAL, "failed to write notes to temp dir"); |
|---|
| | 1366 | goto error; |
|---|
| | 1367 | } |
|---|
| | 1368 | |
|---|
| | 1369 | /* create remote path */ |
|---|
| | 1370 | scpcommand = g_strdup_printf("ssh -o BatchMode=yes %s@%s \"mkdir -p %s\"", |
|---|
| | 1371 | env->username, |
|---|
| | 1372 | env->url, |
|---|
| | 1373 | separator_path); |
|---|
| | 1374 | |
|---|
| | 1375 | scpretval = pclose(popen(scpcommand,"w")); |
|---|
| | 1376 | scpexitstatus = WEXITSTATUS(scpretval); |
|---|
| | 1377 | |
|---|
| | 1378 | if((scpretval == -1) || (scpexitstatus != 0)) { |
|---|
| | 1379 | osync_trace( TRACE_INTERNAL, "failed to create remote path" ); |
|---|
| | 1380 | rc = FALSE; |
|---|
| | 1381 | goto error; |
|---|
| | 1382 | } |
|---|
| | 1383 | g_free(scpcommand); |
|---|
| | 1384 | |
|---|
| | 1385 | /* Copy all text files from the temp path into the remote path */ |
|---|
| | 1386 | scpcommand = g_strdup_printf("scp -q -B %s/* %s@%s:%s", |
|---|
| | 1387 | temppath, |
|---|
| | 1388 | env->username, |
|---|
| | 1389 | env->url, |
|---|
| | 1390 | separator_path); |
|---|
| | 1391 | |
|---|
| | 1392 | scpretval = pclose(popen(scpcommand,"w")); |
|---|
| | 1393 | scpexitstatus = WEXITSTATUS(scpretval); |
|---|
| | 1394 | |
|---|
| | 1395 | if((scpretval == -1) || (scpexitstatus != 0)) { |
|---|
| | 1396 | osync_trace( TRACE_INTERNAL, "scp transfer failed" ); |
|---|
| | 1397 | rc = FALSE; |
|---|
| | 1398 | goto error; |
|---|
| | 1399 | } |
|---|
| | 1400 | else { |
|---|
| | 1401 | osync_trace( TRACE_INTERNAL, "scp transfer ok" ); |
|---|
| | 1402 | } |
|---|
| | 1403 | |
|---|
| | 1404 | /* Delete files that have been deleted */ |
|---|
| | 1405 | |
|---|
| | 1406 | GString *deletedfiles = g_string_new(""); |
|---|
| | 1407 | xmlNode *node = opie_xml_get_first(doc, "notes", "note"); |
|---|
| | 1408 | while(node) { |
|---|
| | 1409 | char *deletedflag = xmlGetProp(node, "deleted"); |
|---|
| | 1410 | if(deletedflag) { |
|---|
| | 1411 | /* This note has been marked deleted, so delete it */ |
|---|
| | 1412 | xmlFree(deletedflag); |
|---|
| | 1413 | |
|---|
| | 1414 | char *notename = xmlGetProp(node, "name"); |
|---|
| | 1415 | if(notename) { |
|---|
| | 1416 | g_string_append_printf(deletedfiles, "%s.txt ", notename); |
|---|
| | 1417 | xmlFree(notename); |
|---|
| | 1418 | } |
|---|
| | 1419 | } |
|---|
| | 1420 | node = opie_xml_get_next(node); |
|---|
| | 1421 | } |
|---|
| | 1422 | |
|---|
| | 1423 | if(deletedfiles->len > 0) { |
|---|
| | 1424 | g_free(scpcommand); |
|---|
| | 1425 | scpcommand = g_strdup_printf("ssh -o BatchMode=yes %s@%s \"cd %s && rm -f %s\"", |
|---|
| | 1426 | env->username, |
|---|
| | 1427 | env->url, |
|---|
| | 1428 | separator_path, |
|---|
| | 1429 | deletedfiles->str); |
|---|
| | 1430 | |
|---|
| | 1431 | scpretval = pclose(popen(scpcommand,"w")); |
|---|
| | 1432 | scpexitstatus = WEXITSTATUS(scpretval); |
|---|
| | 1433 | |
|---|
| | 1434 | if((scpretval == -1) || (scpexitstatus != 0)) { |
|---|
| | 1435 | osync_trace( TRACE_INTERNAL, "ssh delete note files failed" ); |
|---|
| | 1436 | rc = FALSE; |
|---|
| | 1437 | goto error; |
|---|
| | 1438 | } |
|---|
| | 1439 | } |
|---|
| | 1440 | |
|---|
| | 1441 | g_string_free(deletedfiles, TRUE); |
|---|
| | 1442 | } |
|---|
| | 1443 | |
|---|
| | 1444 | error: |
|---|
| | 1445 | |
|---|
| | 1446 | if(temppath) { |
|---|
| | 1447 | /* Delete temp dir (regardless of whether preceding code succeeded) */ |
|---|
| | 1448 | if(!delete_directory(temppath)) |
|---|
| | 1449 | rc = FALSE; |
|---|
| | 1450 | g_free(temppath); |
|---|
| | 1451 | } |
|---|
| | 1452 | |
|---|
| | 1453 | if(separator_path) |
|---|
| | 1454 | g_free(separator_path); |
|---|
| | 1455 | |
|---|
| | 1456 | if(scpcommand); |
|---|
| | 1457 | g_free(scpcommand); |
|---|
| | 1458 | |
|---|
| | 1459 | osync_trace(TRACE_EXIT, "%s(%i)", __func__, rc ); |
|---|
| | 1460 | return rc; |
|---|
| | 1461 | } |
|---|
| | 1462 | |
|---|
| | 1463 | |
|---|
| | 1464 | |
|---|
| | 1465 | |
|---|