/** * infd_chat_filesystem_format_write: * @storage: A #InfdFilesystemStorage. * @path: Storage path where to write the session to. * @buffer: The #InfChatBuffer to write. * @error: Location to store error information, if any, or %NULL. * * Writes the given buffer into the filesystem storage at @path. If * successful, the session can then be read back with * infd_chat_filesystem_format_read(). If the function fails, %FALSE is * returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_chat_filesystem_format_write(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error) { FILE* stream; xmlDocPtr doc; xmlNodePtr root; xmlErrorPtr xmlerror; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfChat", path, "w", NULL, error ); if(stream == NULL) return FALSE; root = xmlNewNode(NULL, (const xmlChar*)"inf-chat-session"); doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); /* TODO: At this point, we should tell libxml2 to use * infd_filesystem_storage_stream_write() instead of fwrite(), * to prevent C runtime mixups. */ if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); g_set_error_literal( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, xmlerror->message ); return FALSE; } infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); return TRUE; }
static gboolean infinoted_plugin_note_chat_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { return infd_chat_filesystem_format_write( INFD_FILESYSTEM_STORAGE(storage), path, INF_CHAT_BUFFER(inf_session_get_buffer(session)), error ); }
static InfSession* infinoted_plugin_note_text_session_read(InfdStorage* storage, InfIo* io, InfCommunicationManager* manager, const gchar* path, gpointer user_data, GError** error) { InfUserTable* user_table; InfTextBuffer* buffer; gboolean result; InfTextSession* session; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); user_table = inf_user_table_new(); buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); result = inf_text_filesystem_format_read( INFD_FILESYSTEM_STORAGE(storage), path, user_table, buffer, error ); if(result == FALSE) { g_object_unref(user_table); g_object_unref(buffer); return NULL; } session = inf_text_session_new_with_user_table( manager, buffer, io, user_table, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(user_table); g_object_unref(buffer); return INF_SESSION(session); }
static InfSession* infinoted_plugin_note_chat_session_read(InfdStorage* storage, InfIo* io, InfCommunicationManager* manager, const gchar* path, gpointer user_data, GError** error) { InfChatBuffer* buffer; gboolean result; InfChatSession* session; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); buffer = inf_chat_buffer_new(256); result = infd_chat_filesystem_format_read( INFD_FILESYSTEM_STORAGE(storage), path, buffer, error ); if(result == FALSE) { g_object_unref(buffer); return NULL; } session = inf_chat_session_new( manager, buffer, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(buffer); return INF_SESSION(session); }
void Gobby::SelfHoster::apply_preferences() { // Update directory storage if(m_preferences.user.keep_local_documents) { InfdStorage* storage = infd_directory_get_storage(m_directory); g_assert(storage == NULL || INFD_IS_FILESYSTEM_STORAGE(storage)); InfdFilesystemStorage* fs_storage = INFD_FILESYSTEM_STORAGE(storage); const std::string new_directory = m_preferences.user.host_directory; bool set_new_storage = true; if(fs_storage != NULL) { gchar* root_directory; g_object_get( G_OBJECT(fs_storage), "root-directory", &root_directory, NULL); if(strcmp(root_directory, new_directory.c_str()) == 0) set_new_storage = false; g_free(root_directory); } if(set_new_storage) { fs_storage = infd_filesystem_storage_new( new_directory.c_str()); g_object_set( G_OBJECT(m_directory), "storage", fs_storage, NULL); g_object_unref(fs_storage); } } else { if(infd_directory_get_storage(m_directory) != NULL) { g_object_set( G_OBJECT(m_directory), "storage", NULL, NULL); } } // Remove old statusbar message, if any if(m_info_handle != m_status_bar.invalid_handle()) { m_status_bar.remove_message(m_info_handle); m_info_handle = m_status_bar.invalid_handle(); } // Close server and all connections if no access is required if(!m_preferences.user.allow_remote_access) { infd_directory_foreach_connection( m_directory, directory_foreach_func_close_static, this); if(m_server.is_open()) m_server.close(); return; } // Okay, we want to share our documents, so let's try to start a // server for it. // Make sure TLS credentials are available. if(m_preferences.security.policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED && (m_preferences.security.authentication_enabled != true || m_cert_manager.get_private_key() == NULL || m_cert_manager.get_certificates() == NULL)) { m_info_handle = m_status_bar.add_info_message( _("In order to start sharing your documents, " "choose a private key and certificate or " "create a new pair in the preferences")); return; } // Make sure we have DH parameters if(!ensure_dh_params()) return; // Okay, go and open a server. If the server is already open the // command below will only change the port and/or security policy. try { const InfKeepalive& keepalive = m_preferences.network.keepalive; m_server.open(m_preferences.user.port, &keepalive, m_preferences.security.policy, m_cert_manager.get_credentials(), m_sasl_context, get_sasl_mechanisms()); } catch(const std::exception& ex) { m_status_bar.add_error_message(_("Failed to share documents"), ex.what()); return; } }
static gboolean infd_note_plugin_text_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { InfUserTable* table; InfTextBuffer* buffer; InfTextBufferIter* iter; xmlNodePtr root; xmlNodePtr buffer_node; xmlNodePtr segment_node; guint author; gchar* content; gsize bytes; FILE* stream; xmlDocPtr doc; xmlErrorPtr xmlerror; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); g_assert(INF_TEXT_IS_SESSION(session)); /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "w", error ); if(stream == NULL) return FALSE; root = xmlNewNode(NULL, (const xmlChar*)"inf-text-session"); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); table = inf_session_get_user_table(session); inf_user_table_foreach_user( table, infd_note_plugin_text_session_write_foreach_user_func, root ); buffer_node = xmlNewChild(root, NULL, (const xmlChar*)"buffer", NULL); iter = inf_text_buffer_create_iter(buffer); if(iter != NULL) { do { author = inf_text_buffer_iter_get_author(buffer, iter); content = inf_text_buffer_iter_get_text(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); segment_node = xmlNewChild( buffer_node, NULL, (const xmlChar*)"segment", NULL ); inf_xml_util_set_attribute_uint(segment_node, "author", author); inf_xml_util_add_child_text(segment_node, content, bytes); g_free(content); } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); fclose(stream); xmlFreeDoc(doc); g_set_error( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, "%s", xmlerror->message ); return FALSE; } fclose(stream); xmlFreeDoc(doc); return TRUE; }
static InfSession* infd_note_plugin_text_session_read(InfdStorage* storage, InfIo* io, InfCommunicationManager* manager, const gchar* path, gpointer user_data, GError** error) { InfUserTable* user_table; InfTextBuffer* buffer; InfTextSession* session; FILE* stream; xmlDocPtr doc; xmlErrorPtr xmlerror; xmlNodePtr root; xmlNodePtr child; gboolean result; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); user_table = inf_user_table_new(); buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); /* TODO: Use a SAX parser for better performance */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "r", error ); if(stream == NULL) return FALSE; doc = xmlReadIO( infd_note_plugin_text_session_read_read_func, infd_note_plugin_text_sesison_read_close_func, stream, path, /* TODO: Get some "infinote-filesystem-storage://" URL? */ "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR ); if(doc == NULL) { xmlerror = xmlGetLastError(); g_set_error( error, g_quark_from_static_string("LIBXML2_PARSER_ERROR"), xmlerror->code, "Error parsing XML in file '%s': [%d]: %s", path, xmlerror->line, xmlerror->message ); result = FALSE; } else { root = xmlDocGetRootElement(doc); if(strcmp((const char*)root->name, "inf-text-session") != 0) { g_set_error( error, g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"), INFD_NOTE_PLUGIN_TEXT_ERROR_NOT_A_TEXT_SESSION, "Error processing file '%s': %s", path, "The document is not a text session" ); result = FALSE; } else { for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "user") == 0) { if(!infd_note_plugin_text_read_user(user_table, child, error)) { g_prefix_error(error, "Error processing file '%s': ", path); result = FALSE; break; } } else if(strcmp((const char*)child->name, "buffer") == 0) { if(!infd_note_plugin_text_read_buffer(buffer, user_table, child, error)) { g_prefix_error(error, "Error processing file '%s': ", path); result = FALSE; break; } } else { infd_note_plugin_text_session_unexpected_node(child, error); g_prefix_error(error, "Error processing file '%s': ", path); result = FALSE; break; } } if(child == NULL) result = TRUE; } xmlFreeDoc(doc); } if(result == FALSE) return NULL; session = inf_text_session_new_with_user_table( manager, buffer, io, user_table, INF_SESSION_RUNNING, NULL, NULL ); return INF_SESSION(session); }
/** * infd_chat_filesystem_format_read: * @storage: A #InfdFilesystemStorage. * @path: Storage path to retrieve the session from. * @buffer: An empty #InfTextBuffer to use as the new session's buffer. * @error: Location to store error information, if any, or %NULL. * * Reads a chat session from @path in @storage. The file is expected to have * been saved with infd_chat_filesystem_format_write() before. The @buffer * parameter should be an empty #InfChatBuffer, and the document will be * written into this buffer. If the function succeeds, the buffer can be used * to create an #InfChatSession with inf_chat_session_new(). If the function * fails, %FALSE is returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_chat_filesystem_format_read(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error) { FILE* stream; gchar* full_path; gchar* uri; xmlDocPtr doc; xmlErrorPtr xmlerror; xmlNodePtr root; xmlNodePtr child; gboolean result; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* TODO: Use a SAX parser for better performance */ full_path = NULL; stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfChat", path, "r", &full_path, error ); if(stream == NULL) { g_free(full_path); return FALSE; } uri = g_filename_to_uri(full_path, NULL, error); g_free(full_path); if(uri == NULL) return FALSE; doc = xmlReadIO( infd_chat_filesystem_format_read_read_func, infd_chat_filesystem_format_read_close_func, stream, uri, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR ); g_free(uri); if(doc == NULL) { xmlerror = xmlGetLastError(); g_set_error( error, g_quark_from_static_string("LIBXML2_PARSER_ERROR"), xmlerror->code, _("Error parsing XML in file \"%s\": [%d]: %s"), path, xmlerror->line, xmlerror->message ); result = FALSE; } else { root = xmlDocGetRootElement(doc); if(strcmp((const char*)root->name, "inf-chat-session") != 0) { g_set_error( error, infd_chat_filesystem_format_error_quark(), INFD_CHAT_FILESYSTEM_FORMAT_ERROR_NOT_A_CHAT_SESSION, _("Error processing file \"%s\": %s"), path, _("The document is not a chat session") ); result = FALSE; } else { result = TRUE; } xmlFreeDoc(doc); } if(result == FALSE) return FALSE; return TRUE; }