avatar.c
changeset 26 fec515d07dd2
parent 25 6ad07b1d4e7f
child 27 c641ef370d18
equal deleted inserted replaced
25:6ad07b1d4e7f 26:fec515d07dd2
    58 	"Provides command /avatar" )
    58 	"Provides command /avatar" )
    59 static const gchar *deps[] = { "pep", NULL };
    59 static const gchar *deps[] = { "pep", NULL };
    60 
    60 
    61 static module_info_t info_avatar_experimental = {
    61 static module_info_t info_avatar_experimental = {
    62 	.branch      = "experimental",
    62 	.branch      = "experimental",
    63 	.api         = 8,
    63 	.api         = 10,
    64 	.version     = PROJECT_VERSION,
    64 	.version     = PROJECT_VERSION,
    65 	.description = DESCRIPTION,
    65 	.description = DESCRIPTION,
    66 	.requires    = deps,
    66 	.requires    = deps,
    67 	.init        = avatar_init,
    67 	.init        = avatar_init,
    68 	.uninit      = avatar_uninit,
    68 	.uninit      = avatar_uninit,
    69 	.next        = NULL,
    69 	.next        = NULL,
    70 };
    70 };
    71 
    71 
    72 module_info_t info_avatar = {
    72 module_info_t info_avatar = {
    73 	.branch      = "dev",
    73 	.branch      = "dev",
    74 	.api         = 7,
    74 	.api         = 11,
    75 	.version     = PROJECT_VERSION,
    75 	.version     = PROJECT_VERSION,
    76 	.description = DESCRIPTION,
    76 	.description = DESCRIPTION,
    77 	.requires    = deps,
    77 	.requires    = deps,
    78 	.init        = avatar_init,
    78 	.init        = avatar_init,
    79 	.uninit      = avatar_uninit,
    79 	.uninit      = avatar_uninit,
    84 
    84 
    85 #define NS_AVATAR_DATA            ( "urn:xmpp:avatar:data"            )
    85 #define NS_AVATAR_DATA            ( "urn:xmpp:avatar:data"            )
    86 #define NS_AVATAR_METADATA        ( "urn:xmpp:avatar:metadata"        )
    86 #define NS_AVATAR_METADATA        ( "urn:xmpp:avatar:metadata"        )
    87 #define NS_AVATAR_METADATA_NOTIFY ( "urn:xmpp:avatar:metadata+notify" )
    87 #define NS_AVATAR_METADATA_NOTIFY ( "urn:xmpp:avatar:metadata+notify" )
    88 
    88 
    89 static guint avatar_cid = 0;
    89 static guint avatar_cid            = 0;
       
    90 static guint avatar_hid_connect    = 0;
       
    91 static guint avatar_hid_disconnect = 0;
    90 
    92 
    91 static GSList *reply_handlers = NULL;
    93 static GSList *reply_handlers = NULL;
    92 
    94 
    93 static LmMessageHandler *avatar_metadata_reply_handler = NULL;
    95 static LmMessageHandler *avatar_metadata_reply_handler = NULL;
    94 
    96 
   504 	if (!jfile)
   506 	if (!jfile)
   505 		return;
   507 		return;
   506 	
   508 	
   507 	unlink (jfile);
   509 	unlink (jfile);
   508 	if (symlink (file, jfile) == -1)
   510 	if (symlink (file, jfile) == -1)
   509 		scr_LogPrint (LPRINT_LOGNORM, "avatar: Cannot symlink jid-file to avatar: %s.", strerror (errno));
   511 		scr_log_print (LPRINT_LOGNORM, "avatar: Cannot symlink jid-file to avatar: %s.", strerror (errno));
   510 }
   512 }
   511 
   513 
   512 // reply handler for metadata publish request
   514 // reply handler for metadata publish request
   513 // just prints error message if unsuccessful
   515 // just prints error message if unsuccessful
   514 static LmHandlerResult avatar_publish_metadata_reply_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer userdata)
   516 static LmHandlerResult avatar_publish_metadata_reply_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer userdata)
   529 			if (node->children)
   531 			if (node->children)
   530 				reason = node->children->name;
   532 				reason = node->children->name;
   531 			else
   533 			else
   532 				reason = "undefined";
   534 				reason = "undefined";
   533 	
   535 	
   534 			scr_LogPrint (LPRINT_LOGNORM, "avatar: Metadata publishing failed: %s - %s.", type, reason);
   536 			scr_log_print (LPRINT_LOGNORM, "avatar: Metadata publishing failed: %s - %s.", type, reason);
   535 		}
   537 		}
   536 
   538 
   537 		break;
   539 		break;
   538 
   540 
   539 	default:
   541 	default:
   559 			GError *error = NULL;
   561 			GError *error = NULL;
   560 
   562 
   561 			lm_connection_send_with_reply (connection, request, avatar_metadata_reply_handler, &error);
   563 			lm_connection_send_with_reply (connection, request, avatar_metadata_reply_handler, &error);
   562 
   564 
   563 			if (error) {
   565 			if (error) {
   564 				scr_LogPrint (LPRINT_DEBUG, "avatar: Metadata publication error: %s.", error -> message);
   566 				scr_log_print (LPRINT_DEBUG, "avatar: Metadata publication error: %s.", error -> message);
   565 				g_error_free (error);
   567 				g_error_free (error);
   566 			}
   568 			}
   567 
   569 
   568 			lm_message_unref (request);
   570 			lm_message_unref (request);
   569 		}
   571 		}
   582 			if (node->children)
   584 			if (node->children)
   583 				reason = node->children->name;
   585 				reason = node->children->name;
   584 			else
   586 			else
   585 				reason = "undefined";
   587 				reason = "undefined";
   586 
   588 
   587 			scr_LogPrint (LPRINT_LOGNORM, "avatar: Data publishing failed: %s - %s.", type, reason);
   589 			scr_log_print (LPRINT_LOGNORM, "avatar: Data publishing failed: %s - %s.", type, reason);
   588 		}
   590 		}
   589 
   591 
   590 		break;
   592 		break;
   591 
   593 
   592 	default:
   594 	default:
   616 			gchar         *bjid;
   618 			gchar         *bjid;
   617 			LmMessage     *request;
   619 			LmMessage     *request;
   618 			LmMessageNode *node;
   620 			LmMessageNode *node;
   619 
   621 
   620 			if (!xmpp_is_online ()) {
   622 			if (!xmpp_is_online ()) {
   621 				scr_LogPrint (LPRINT_NORMAL, "avatar: You are not online, request not sent.");
   623 				scr_log_print (LPRINT_NORMAL, "avatar: You are not online, request not sent.");
   622 				return FALSE;
   624 				return FALSE;
   623 			}
   625 			}
   624 
   626 
   625 			bjid = jidtodisp (jid);
   627 			bjid = jidtodisp (jid);
   626 
   628 
   627 			scr_WriteIncomingMessage (bjid, "No avatar for this buddy yet, sending request.", 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   629 			scr_write_incoming_message (bjid, "No avatar for this buddy yet, sending request.", 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   628 
   630 
   629 			// create data request
   631 			// create data request
   630 			request = lm_message_new_with_sub_type (bjid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   632 			request = lm_message_new_with_sub_type (bjid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   631 			node = lm_message_get_node (request);
   633 			node = lm_message_get_node (request);
   632 			lm_message_node_set_attribute (node, "from", lm_connection_get_jid (lconnection));
   634 			lm_message_node_set_attribute (node, "from", lm_connection_get_jid (lconnection));
   641 				GError *error = NULL;
   643 				GError *error = NULL;
   642 
   644 
   643 				lm_connection_send (lconnection, request, &error);
   645 				lm_connection_send (lconnection, request, &error);
   644 
   646 
   645 				if (error) {
   647 				if (error) {
   646 					scr_LogPrint (LPRINT_DEBUG, "avatar: Request sending error: %s.", error -> message);
   648 					scr_log_print (LPRINT_DEBUG, "avatar: Request sending error: %s.", error -> message);
   647 					g_error_free (error);
   649 					g_error_free (error);
   648 				}
   650 				}
   649 			}
   651 			}
   650 
   652 
   651 			lm_message_unref (request);
   653 			lm_message_unref (request);
   659 	
   661 	
   660 		row_pointers = png_read_file (file, &width, &height, background);
   662 		row_pointers = png_read_file (file, &width, &height, background);
   661 	}
   663 	}
   662 
   664 
   663 	if (!row_pointers) {
   665 	if (!row_pointers) {
   664 		scr_LogPrint (LPRINT_LOGNORM, "avatar: Cannot decode png data from file %s.", file);
   666 		scr_log_print (LPRINT_LOGNORM, "avatar: Cannot decode png data from file %s.", file);
   665 		return FALSE;
   667 		return FALSE;
   666 	}
   668 	}
   667 
   669 
   668 	{ // convert to ascii
   670 	{ // convert to ascii
   669 		int maxcharh = settings_opt_get_int ("avatar_max_height");
   671 		int maxcharh = settings_opt_get_int ("avatar_max_height");
   687 	}
   689 	}
   688 
   690 
   689 	g_free (row_pointers);
   691 	g_free (row_pointers);
   690 
   692 
   691 	if (!avatar) {
   693 	if (!avatar) {
   692 		scr_LogPrint (LPRINT_LOGNORM, "avatar: Error converting image to ascii.");
   694 		scr_log_print (LPRINT_LOGNORM, "avatar: Error converting image to ascii.");
   693 		return FALSE;
   695 		return FALSE;
   694 	}
   696 	}
   695 
   697 
   696 	{ // print out avatar
   698 	{ // print out avatar
   697 		gchar *bjid = jidtodisp (jid);
   699 		gchar *bjid = jidtodisp (jid);
   699 		if (id)
   701 		if (id)
   700 			mesg = g_strdup_printf ("Avatar [%s]:\n%s", id, avatar);
   702 			mesg = g_strdup_printf ("Avatar [%s]:\n%s", id, avatar);
   701 		else
   703 		else
   702 			mesg = g_strdup_printf ("Avatar:\n%s", avatar);
   704 			mesg = g_strdup_printf ("Avatar:\n%s", avatar);
   703 
   705 
   704 		scr_WriteIncomingMessage (bjid, mesg, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   706 		scr_write_incoming_message (bjid, mesg, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   705 
   707 
   706 		g_free (bjid);
   708 		g_free (bjid);
   707 		g_free (mesg);
   709 		g_free (mesg);
   708 	}
   710 	}
   709 
   711 
   767 	
   769 	
   768 							{ // write image to file
   770 							{ // write image to file
   769 								int fd = open (file, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
   771 								int fd = open (file, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
   770 
   772 
   771 								if (fd == -1) {
   773 								if (fd == -1) {
   772 									scr_LogPrint (LPRINT_LOGNORM, "avatar: Cannot create file: %s.", strerror (errno));
   774 									scr_log_print (LPRINT_LOGNORM, "avatar: Cannot create file: %s.", strerror (errno));
   773 									g_free (png);
   775 									g_free (png);
   774 									g_free (file);
   776 									g_free (file);
   775 									continue;
   777 									continue;
   776 								}
   778 								}
   777 
   779 
   808 			if (node->children)
   810 			if (node->children)
   809 				reason = node->children->name;
   811 				reason = node->children->name;
   810 			else
   812 			else
   811 				reason = "undefined";
   813 				reason = "undefined";
   812 
   814 
   813 			scr_LogPrint (LPRINT_LOGNORM, "avatar: Obtaining avatar data for %s failed: %s - %s.", from, type, reason);
   815 			scr_log_print (LPRINT_LOGNORM, "avatar: Obtaining avatar data for %s failed: %s - %s.", from, type, reason);
   814 		}
   816 		}
   815 
   817 
   816 		break;
   818 		break;
   817 
   819 
   818 	default:
   820 	default:
   833 	LmMessage        *request;
   835 	LmMessage        *request;
   834 	LmMessageNode    *node;
   836 	LmMessageNode    *node;
   835 	GError           *error       = NULL;
   837 	GError           *error       = NULL;
   836 
   838 
   837 	if (!xmpp_is_online ()) {
   839 	if (!xmpp_is_online ()) {
   838 		scr_LogPrint (LPRINT_DEBUG, "avatar: Not connected, delaying publish.");
   840 		scr_log_print (LPRINT_DEBUG, "avatar: Not connected, delaying publish.");
   839 
   841 
   840 		g_free (publish_data);
   842 		g_free (publish_data);
   841 
   843 
   842 		publish_data    = g_strndup (data, len);
   844 		publish_data    = g_strndup (data, len);
   843 		publish_len     = len;
   845 		publish_len     = len;
   911 	} else 
   913 	} else 
   912 		// send
   914 		// send
   913 		lm_connection_send_with_reply (lconnection, request, avatar_metadata_reply_handler, &error);
   915 		lm_connection_send_with_reply (lconnection, request, avatar_metadata_reply_handler, &error);
   914 	
   916 	
   915 	if (error) {
   917 	if (error) {
   916 		scr_LogPrint (LPRINT_DEBUG, "avatar: Publish request sending error: %s.", error -> message);
   918 		scr_log_print (LPRINT_DEBUG, "avatar: Publish request sending error: %s.", error -> message);
   917 		g_error_free (error);
   919 		g_error_free (error);
   918 	}
   920 	}
   919 
   921 
   920 	lm_message_unref (request);
   922 	lm_message_unref (request);
   921 }
   923 }
   963 					g_string_append (mesg, url);
   965 					g_string_append (mesg, url);
   964 				}
   966 				}
   965 
   967 
   966 				text = g_string_free (mesg, FALSE);
   968 				text = g_string_free (mesg, FALSE);
   967 
   969 
   968 				scr_WriteIncomingMessage (jid, text, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   970 				scr_write_incoming_message (jid, text, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
   969 
   971 
   970 				g_free (text);
   972 				g_free (text);
   971 			}
   973 			}
   972 
   974 
   973 			if (!url) {
   975 			if (!url) {
   979 				{ // check, if file already exists
   981 				{ // check, if file already exists
   980 					gchar       *file = avatar_id_filename (id);
   982 					gchar       *file = avatar_id_filename (id);
   981 					struct stat  buf;
   983 					struct stat  buf;
   982 
   984 
   983 					if (!file) {
   985 					if (!file) {
   984 						scr_LogPrint (LPRINT_LOGNORM, "avatar: Cannot obtain filename to save file, probably avatar_directory is not set.");
   986 						scr_log_print (LPRINT_LOGNORM, "avatar: Cannot obtain filename to save file, probably avatar_directory is not set.");
   985 						g_free (jid);
   987 						g_free (jid);
   986 						continue;
   988 						continue;
   987 					}
   989 					}
   988 					
   990 					
   989 					if (stat (file, &buf) != -1) {
   991 					if (stat (file, &buf) != -1) {
   990 						scr_WriteIncomingMessage (jid, "Avatar file exists, will not download.", 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
   992 						scr_write_incoming_message (jid, "Avatar file exists, will not download.", 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
   991 						// link jid to this file
   993 						// link jid to this file
   992 						set_jid_avatar (jid, file);
   994 						set_jid_avatar (jid, file);
   993 						g_free (file);
   995 						g_free (file);
   994 						g_free (jid);
   996 						g_free (jid);
   995 						continue;
   997 						continue;
  1020 					GError *error = NULL;
  1022 					GError *error = NULL;
  1021 
  1023 
  1022 					lm_connection_send_with_reply (lconnection, request, dhandler, &error);
  1024 					lm_connection_send_with_reply (lconnection, request, dhandler, &error);
  1023 
  1025 
  1024 					if (error) {
  1026 					if (error) {
  1025 						scr_LogPrint (LPRINT_DEBUG, "avatar: Data request sending error: %s.", error -> message);
  1027 						scr_log_print (LPRINT_DEBUG, "avatar: Data request sending error: %s.", error -> message);
  1026 						g_error_free (error);
  1028 						g_error_free (error);
  1027 					}
  1029 					}
  1028 				}
  1030 				}
  1029 
  1031 
  1030 				lm_message_handler_unref (dhandler);
  1032 				lm_message_handler_unref (dhandler);
  1046 
  1048 
  1047 	if (!*arg) { // print current byddy's avatar
  1049 	if (!*arg) { // print current byddy's avatar
  1048 		const gchar *jid = CURRENT_JID;
  1050 		const gchar *jid = CURRENT_JID;
  1049 
  1051 
  1050 		if (!jid) {
  1052 		if (!jid) {
  1051 			scr_LogPrint (LPRINT_NORMAL, "This item cannot have avatar.");
  1053 			scr_log_print (LPRINT_NORMAL, "This item cannot have avatar.");
  1052 			return;
  1054 			return;
  1053 		}
  1055 		}
  1054 
  1056 
  1055 		fname = avatar_jid_filename (jid);
  1057 		fname = avatar_jid_filename (jid);
  1056 
  1058 
  1073 		char     buffer[1024];
  1075 		char     buffer[1024];
  1074 		GString *datastring;
  1076 		GString *datastring;
  1075 		int      fd           = open (fname, O_RDONLY);
  1077 		int      fd           = open (fname, O_RDONLY);
  1076 
  1078 
  1077 		if (!fd) {
  1079 		if (!fd) {
  1078 			scr_LogPrint (LPRINT_NORMAL, "Cannot open file '%s': %s.", fname, strerror (errno));
  1080 			scr_log_print (LPRINT_NORMAL, "Cannot open file '%s': %s.", fname, strerror (errno));
  1079 			g_free (fname);
  1081 			g_free (fname);
  1080 			return;
  1082 			return;
  1081 		}
  1083 		}
  1082 
  1084 
  1083 		datastring = g_string_new (NULL);
  1085 		datastring = g_string_new (NULL);
  1122 		lm_connection_unregister_reply_handler (lconnection, avatar_metadata_reply_handler);
  1124 		lm_connection_unregister_reply_handler (lconnection, avatar_metadata_reply_handler);
  1123 #endif
  1125 #endif
  1124 }
  1126 }
  1125 
  1127 
  1126 // release handlers before reconnect
  1128 // release handlers before reconnect
  1127 static void avatar_hh (guint32 hid, hk_arg_t *args, gpointer userdata)
  1129 static guint avatar_hdh (const gchar *hid, hk_arg_t *args, gpointer userdata)
  1128 {
  1130 {
  1129 	if (hid == HOOK_PRE_DISCONNECT)
  1131 	avatar_free_reply_handlers ();
  1130 
  1132 	return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  1131 		avatar_free_reply_handlers ();
  1133 }
  1132 
  1134 
  1133 	else if (hid == HOOK_POST_CONNECT && publish_delayed) {
  1135 static guint avatar_hch (const gchar *hid, hk_arg_t *args, gpointer userdata)
  1134 
  1136 {
       
  1137 	if (publish_data) {
  1135 		char *tmp_data = publish_data;
  1138 		char *tmp_data = publish_data;
  1136 
  1139 
  1137 		scr_LogPrint (LPRINT_DEBUG, "avatar: Publishing delayed data.");
  1140 		scr_log_print (LPRINT_DEBUG, "avatar: Publishing delayed data.");
  1138 
  1141 
  1139 		publish_data    = NULL;
  1142 		publish_data    = NULL;
  1140 		publish_delayed = FALSE;
  1143 		publish_delayed = FALSE;
  1141 
  1144 
  1142 		avatar_publish (publish_data, publish_len);
  1145 		avatar_publish (publish_data, publish_len);
  1143 
  1146 
  1144 		g_free (tmp_data);
  1147 		g_free (tmp_data);
  1145 	}
  1148 	}
       
  1149 
       
  1150 	return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  1146 }
  1151 }
  1147 
  1152 
  1148 static void avatar_init (void)
  1153 static void avatar_init (void)
  1149 {
  1154 {
  1150 	pep_register_xmlns_handler (NS_AVATAR_METADATA, avatar_handler, NULL, NULL);
  1155 	pep_register_xmlns_handler (NS_AVATAR_METADATA, avatar_handler, NULL, NULL);
  1151 	avatar_metadata_reply_handler = lm_message_handler_new (avatar_publish_metadata_reply_handler, NULL, NULL);
  1156 	avatar_metadata_reply_handler = lm_message_handler_new (avatar_publish_metadata_reply_handler, NULL, NULL);
  1152 
  1157 
  1153 	cmd_add ("avatar", "", COMPL_FILENAME, 0, do_avatar, NULL);
  1158 	cmd_add ("avatar", "", COMPL_FILENAME, 0, do_avatar, NULL);
  1154 
  1159 
  1155 	hk_add_handler (avatar_hh, HOOK_PRE_DISCONNECT | HOOK_POST_CONNECT, NULL);
  1160 	avatar_hid_connect    = hk_add_handler (avatar_hch, HOOK_POST_CONNECT, G_PRIORITY_DEFAULT, NULL);
       
  1161 	avatar_hid_disconnect = hk_add_handler (avatar_hdh, HOOK_PRE_DISCONNECT, G_PRIORITY_DEFAULT, NULL);
  1156 
  1162 
  1157 	xmpp_add_feature (NS_AVATAR_METADATA);
  1163 	xmpp_add_feature (NS_AVATAR_METADATA);
  1158 	xmpp_add_feature (NS_AVATAR_METADATA_NOTIFY);
  1164 	xmpp_add_feature (NS_AVATAR_METADATA_NOTIFY);
  1159 }
  1165 }
  1160 
  1166 
  1161 static void avatar_uninit (void)
  1167 static void avatar_uninit (void)
  1162 {
  1168 {
  1163 	xmpp_del_feature (NS_AVATAR_METADATA);
  1169 	xmpp_del_feature (NS_AVATAR_METADATA);
  1164 	xmpp_del_feature (NS_AVATAR_METADATA_NOTIFY);
  1170 	xmpp_del_feature (NS_AVATAR_METADATA_NOTIFY);
  1165 
  1171 
  1166 	hk_del_handler (avatar_hh, NULL);
  1172 	hk_del_handler (HOOK_POST_CONNECT, avatar_hid_connect);
       
  1173 	hk_del_handler (HOOK_PRE_DISCONNECT, avatar_hid_disconnect);
  1167 
  1174 
  1168 	cmd_del ("avatar");
  1175 	cmd_del ("avatar");
  1169 
  1176 
  1170 	pep_unregister_xmlns_handler (NS_AVATAR_METADATA);
  1177 	pep_unregister_xmlns_handler (NS_AVATAR_METADATA);
  1171 
  1178