static void connect(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, ctx);
	//Each time you get passed a context (which is used to track
	//calls to your plugin) you can get the data your returned in
	//initialize via this call:
	// plugin_environment *env = (plugin_environment *)userdata;

	//The sink specific userdata you can get with this calls:
	OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
	sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink);


	OSyncError *error = NULL;

	/*
	 * Now connect to your devices and report
	 * 
	 * an error via:
	 * osync_context_report_error(ctx, ERROR_CODE, "Some message");
	 * 
	 * or success via:
	 * osync_context_report_success(ctx);
	 * 
	 * You have to use one of these 2 somewhere to answer the context.
	 * 
	 */


	//If you need a hashtable you make it here
	char *tablepath = osync_strdup_printf("%s/hashtable.db", osync_plugin_info_get_configdir(info));
	sinkenv->hashtable = osync_hashtable_new(tablepath, osync_objtype_sink_get_name(sink), &error);
	osync_free(tablepath);

	if (!sinkenv->hashtable)
		goto error;

	//you can also use the anchor system to detect a device reset
	//or some parameter change here. Check the docs to see how it works
	char *lanchor = NULL;
	//Now you get the last stored anchor from the device
	char *anchorpath = osync_strdup_printf("%s/anchor.db", osync_plugin_info_get_configdir(info));

	if (!osync_anchor_compare(anchorpath, "lanchor", lanchor))
		osync_objtype_sink_set_slowsync(sink, TRUE);

	osync_free(anchorpath);

	osync_context_report_success(ctx);
	osync_trace(TRACE_EXIT, "%s", __func__);
	return;

error:
	osync_context_report_osyncerror(ctx, error);
	osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error));
	osync_error_unref(&error);
}
Exemple #2
0
static char *print_file(const char *data, unsigned int size, void *user_data, OSyncError **error)
{
	OSyncFileFormat *file = (OSyncFileFormat *)data;

	char *printable = osync_strdup_printf ("File %s: size: %i", file->path, file->size);
	return printable;
}
static void sync_done(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx)
{
	/*
	 * This function will only be called if the sync was successful
	 */
	OSyncError *error = NULL;
	OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
	sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink);
	
	//If we use anchors we have to update it now.
	//Now you get/calculate the current anchor of the device
	char *lanchor = NULL;
	char *anchorpath = osync_strdup_printf("%s/anchor.db", osync_plugin_info_get_configdir(info));
	osync_anchor_update(anchorpath, "lanchor", lanchor);
	osync_free(anchorpath);
	//Save hashtable to database
	if (!osync_hashtable_save(sinkenv->hashtable, &error))
		goto error;
	
	//Answer the call
	osync_context_report_success(ctx);
	return;
error:
	osync_context_report_osyncerror(ctx, error);
	osync_error_unref(&error);
	return;
}
osync_bool osync_capabilities_assemble(OSyncCapabilities *capabilities, char **buffer, unsigned int *size, OSyncError **error)
{
	xmlDocPtr doc = NULL;
	xmlNodePtr root;
	char *version_str;
	const char *capsformat;
	OSyncList *l;
	osync_assert(capabilities);

	capsformat = osync_capabilities_get_format(capabilities);

	if (!capsformat) {
		osync_error_set(error, OSYNC_ERROR_GENERIC, "Can't assamble capabilities: Capabilities Format not set.");
		goto error;
	}

	if (capabilities->doc)
		osync_xml_free_doc(capabilities->doc);

	capabilities->doc = doc = xmlNewDoc(BAD_CAST "1.0");
	capabilities->doc->children = xmlNewDocNode(capabilities->doc, NULL, (xmlChar *)"Caps", NULL);
	capabilities->doc->_private = capabilities;

        /* Set version for capabilities configuration */
        version_str = osync_strdup_printf("%u.%u", OSYNC_CAPS_MAJOR_VERSION, OSYNC_CAPS_MINOR_VERSION);
        xmlSetProp(doc->children, (const xmlChar*)"Version", (const xmlChar *)version_str);
        osync_free(version_str);

	/* Set CapsFormat Name */
        xmlSetProp(doc->children, (const xmlChar*)"CapsFormat", (const xmlChar *)capsformat);

	root = doc->children;

	for (l = capabilities->objtypes; l; l = l->next) {
		OSyncCapabilitiesObjType *capobjtype;
		capobjtype = (OSyncCapabilitiesObjType *) l->data;
		if (!osync_capabilities_objtype_assemble(capobjtype, root, error))
			goto error;
	}

	/* XXX Ugly cast, but we try to fit here the opensync API pattern of unsigned size/length types */
	xmlDocDumpFormatMemoryEnc(doc, (xmlChar **) buffer, (int *) size, NULL, 1);
	
	return TRUE;

/*
error_oom:
	osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't allocate memory to assemble capabilities file.");
*/	
error:
	osync_trace(TRACE_EXIT_ERROR, "%s: %s" , __func__, osync_error_print(error));
	return FALSE;
}
OSyncCapabilities *osync_capabilities_load_identifier(const char *file, OSyncError **error)
{
	char *filename;
	OSyncCapabilities *capabilities;

	osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, file, error);
	osync_assert(file);
	
	filename = osync_strdup_printf("%s%c%s", OPENSYNC_CAPABILITIESDIR, G_DIR_SEPARATOR, file);
	
	capabilities = osync_capabilities_load(filename, error);
	if (!capabilities)
		goto error;
	
	osync_trace(TRACE_EXIT, "%s: %p", __func__, capabilities);
	return capabilities;

error:	
	osync_trace(TRACE_EXIT_ERROR, "%s: %s" , __func__, osync_error_print(error));
	return NULL;
}
osync_bool osync_db_reset_table(OSyncDB *db, const char *tablename, OSyncError **error)
{
	char *query = NULL;
	osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, db, tablename, error);

	osync_assert(db);
	osync_assert(tablename);
	
	query = osync_strdup_printf("DELETE FROM %s", tablename);

	if (!osync_db_query(db, query, error))
		goto error;

	osync_free(query);
	
	osync_trace(TRACE_EXIT, "%s", __func__);
	return TRUE;
 error:
	osync_free(query);
	osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));	
	return FALSE;
}
int osync_db_table_exists(OSyncDB *db, const char *tablename, OSyncError **error)
{
	sqlite3_stmt *ppStmt = NULL;
	char *query = NULL;

	osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, db, tablename, error);

	osync_assert(db);
	osync_assert(tablename);

	query = osync_strdup_printf("SELECT name FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type='table' AND name='%s'",
	                        tablename);

	if (sqlite3_prepare(db->sqlite3db, query, -1, &ppStmt, NULL) != SQLITE_OK) {
		sqlite3_finalize(ppStmt);
		osync_free(query);

		osync_error_set(error, OSYNC_ERROR_GENERIC, "Query Error: %s", sqlite3_errmsg(db->sqlite3db));
		osync_trace(TRACE_EXIT_ERROR, "Database query error: %s", sqlite3_errmsg(db->sqlite3db));
		return -1;
	}


	if (sqlite3_step(ppStmt) != SQLITE_ROW) {
		sqlite3_finalize(ppStmt);
		osync_free(query);

		osync_trace(TRACE_EXIT, "%s: table \"%s\" doesn't exist.", __func__, tablename);
		return 0;
	}

	sqlite3_finalize(ppStmt);
	osync_free(query);
	
	osync_trace(TRACE_EXIT, "%s: table \"%s\" exists.", __func__, tablename);
	return 1;
}
static void *initialize(OSyncPlugin *plugin, OSyncPluginInfo *info, OSyncError **error)
{
	/*
	 * get the config
	 */
	OSyncPluginConfig *config = osync_plugin_info_get_config(info);
	if (!config) {
		osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to get config.");
		goto error;
	}
	/*
	 * You need to specify the <some name>_environment somewhere with
	 * all the members you need
	*/
	plugin_environment *env = osync_try_malloc0(sizeof(plugin_environment), error);
	if (!env)
		goto error;

	env->sink_envs = NULL;
	
	osync_trace(TRACE_INTERNAL, "The config: %s", osync_plugin_info_get_config(info));

	/* 
	 * Process the config here and set the options on your environment
	*/
	/*
	 * Process plugin specific advanced options 
	 */
	OSyncList *optslist = osync_plugin_config_get_advancedoptions(config);
	for (; optslist; optslist = optslist->next) {
		OSyncPluginAdvancedOption *option = optslist->data;

		const char *val = osync_plugin_advancedoption_get_value(option);
		const char *name = osync_plugin_advancedoption_get_name(option);

		if (!strcmp(name,"<your-option>")) {
			if (!strcmp(val, "<your-value>")) {
				/*
				 * set a varaible to a specific value
				 */;
			}
		}
	}
	/*
	 * Process Ressource options
	 */
	int i, numobjs = osync_plugin_info_num_objtypes(info);
	for (i = 0; i < numobjs; i++) {
		sink_environment *sinkenv = osync_try_malloc0(sizeof(sink_environment), error);
		if (!sinkenv)
			goto error_free_env;

		sinkenv->sink = osync_plugin_info_nth_objtype(info, i);
		osync_assert(sinkenv->sink);

		const char *objtype = osync_objtype_sink_get_name(sinkenv->sink);
		OSyncPluginResource *res = osync_plugin_config_find_active_resource(config, objtype);
		
		/* get objformat sinks */
		OSyncList *s = osync_plugin_resource_get_objformat_sinks(res);
		for (; s; s = s->next) {
			OSyncObjFormatSink *fsink = s->data; // there could be only one sink
			const char *objformat = osync_objformat_sink_get_objformat(fsink);
			osync_assert(objformat);
			osync_trace(TRACE_INTERNAL, "objtype %s has objformat %s", objtype, objformat);
		}	

		/* Every sink can have different functions ... */
		OSyncObjTypeSinkFunctions functions;
		memset(&functions, 0, sizeof(functions));
		functions.connect = connect;
		functions.disconnect = disconnect;
		functions.get_changes = get_changes;
		functions.commit = commit_change;
		functions.sync_done = sync_done;

		/* We pass the OSyncFileDir object to the sink, so we dont have to look it up
		 * again once the functions are called */
		osync_objtype_sink_set_functions(sinkenv->sink, functions, sinkenv);
		
		osync_trace(TRACE_INTERNAL, "The configdir: %s", osync_plugin_info_get_configdir(info));
		char *tablepath = osync_strdup_printf("%s/hashtable.db", osync_plugin_info_get_configdir(info));
		sinkenv->hashtable = osync_hashtable_new(tablepath, objtype, error);
		osync_free(tablepath);
		env->sink_envs = osync_list_append(env->sink_envs, sinkenv);
	}
	
	//Now your return your struct.
	return (void *) env;

error_free_env:
	free_env(env);
error:
	osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
	return NULL;
}
OSyncList *osync_version_load_from_descriptions(OSyncError **error, const char *descriptiondir, const char *schemadir)
{
	GDir *dir = NULL;
	GError *gerror = NULL;
	const char *descpath = descriptiondir ? descriptiondir : OPENSYNC_DESCRIPTIONSDIR; 
	const char *schemapath = schemadir ? schemadir : OPENSYNC_SCHEMASDIR; 
	char *filename = NULL;
	const gchar *de = NULL;
	OSyncList *versions = NULL;
	OSyncVersion *version = NULL;
	xmlDocPtr doc;
	xmlNodePtr root;
	xmlNodePtr cur;
	xmlNodePtr child;
	
	osync_trace(TRACE_ENTRY, "%s(%p)", __func__, error);
	
	dir = g_dir_open(descpath, 0, &gerror);
	if (!dir) {
		/* If description directory doesn't exist (e.g. unittests), just ignore this. */
		osync_trace(TRACE_EXIT, "Unable to open directory %s: %s", descpath, gerror->message);
		g_error_free(gerror);
		return NULL;
	}
	
	while ((de = g_dir_read_name(dir))) {
		char *schemafilepath = NULL;
		osync_bool res;

		filename = osync_strdup_printf ("%s%c%s", descpath, G_DIR_SEPARATOR, de);
		
		if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR) || !g_pattern_match_simple("*.xml", filename)) {
			osync_free(filename);
			continue;
		}
		
		doc = xmlReadFile(filename, NULL, XML_PARSE_NOBLANKS);
		if(!doc) {
			osync_free(filename);
			continue;
		}
		
		osync_free(filename);
		
		root = xmlDocGetRootElement(doc);
		if(!root || !xmlStrEqual(root->name, BAD_CAST "versions")) {
			osync_xml_free_doc(doc);
			continue;
		}

		schemafilepath = osync_strdup_printf("%s%c%s", schemapath, G_DIR_SEPARATOR, "descriptions.xsd");
		res = osync_xml_validate_document(doc, schemafilepath);
		osync_free(schemafilepath);

		if(res == FALSE) {
			osync_xml_free_doc(doc);
			continue;
		}
		
		cur = root->children;
		for(; cur != NULL; cur = cur->next) {
		
			version = osync_version_new(error);
			if(!version) {
				OSyncList *cur = NULL;
				osync_xml_free_doc(doc);
				cur = osync_list_first(versions);
				while(cur) {
					osync_version_unref(cur->data);
					cur = cur->next;	
				}
				goto error;
			}
				
			child = cur->children;
			osync_version_set_plugin(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_priority(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_vendor(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_modelversion(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_firmwareversion(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_softwareversion(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_hardwareversion(version, (const char *)osync_xml_node_get_content(child));
			child = child->next;
			osync_version_set_identifier(version, (const char *)osync_xml_node_get_content(child));
			
			versions = osync_list_append(versions, version);
		}
		
		osync_xml_free_doc(doc);
	}
	
	g_dir_close(dir);
	
	osync_trace(TRACE_EXIT, "%s: %p", __func__, versions);
	return versions;

 error:
	osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
	return NULL;
}