Gadu-Gadu: setting public profile information. Fixes #6918
1.1 --- a/libpurple/protocols/gg/gg.c
1.2 +++ b/libpurple/protocols/gg/gg.c
1.3 @@ -1301,6 +1301,11 @@
1.4 ggp_pubdir_search((PurpleConnection *)action->context, NULL);
1.5 }
1.6
1.7 +static void ggp_action_set_info(PurplePluginAction *action)
1.8 +{
1.9 + ggp_pubdir_set_info((PurpleConnection *)action->context);
1.10 +}
1.11 +
1.12 static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
1.13 {
1.14 GList *m = NULL;
1.15 @@ -1310,12 +1315,18 @@
1.16 ggp_action_chpass);
1.17 m = g_list_append(m, act);
1.18
1.19 + act = purple_plugin_action_new(_("Show status only for buddies"),
1.20 + ggp_action_status_broadcasting);
1.21 + m = g_list_append(m, act);
1.22 +
1.23 + m = g_list_append(m, NULL);
1.24 +
1.25 act = purple_plugin_action_new(_("Find buddies..."),
1.26 ggp_action_search);
1.27 m = g_list_append(m, act);
1.28
1.29 - act = purple_plugin_action_new(_("Show status only for buddies"),
1.30 - ggp_action_status_broadcasting);
1.31 + act = purple_plugin_action_new(_("Set User Info"),
1.32 + ggp_action_set_info);
1.33 m = g_list_append(m, act);
1.34
1.35 m = g_list_append(m, NULL);
2.1 --- a/libpurple/protocols/gg/pubdir-prpl.c
2.2 +++ b/libpurple/protocols/gg/pubdir-prpl.c
2.3 @@ -87,6 +87,42 @@
2.4 static void ggp_pubdir_search_results_new(PurpleConnection *gc, GList *row,
2.5 gpointer _form);
2.6
2.7 +// Own profile.
2.8 +
2.9 +static void ggp_pubdir_set_info_dialog(PurpleConnection *gc, int records_count,
2.10 + const ggp_pubdir_record *records, int next_offset, void *user_data);
2.11 +static void ggp_pubdir_set_info_request(PurpleConnection *gc,
2.12 + PurpleRequestFields *fields);
2.13 +static void ggp_pubdir_set_info_got_token(PurpleConnection *gc,
2.14 + const gchar *token, gpointer _record);
2.15 +static void ggp_pubdir_set_info_got_response(PurpleUtilFetchUrlData *url_data,
2.16 + gpointer user_data, const gchar *url_text, gsize len,
2.17 + const gchar *error_message);
2.18 +
2.19 +/******************************************************************************/
2.20 +
2.21 +static const gchar *ggp_pubdir_provinces[] =
2.22 +{
2.23 + "dolnośląskie",
2.24 + "kujawsko-pomorskie",
2.25 + "lubelskie",
2.26 + "lubuskie",
2.27 + "łódzkie",
2.28 + "małopolskie",
2.29 + "mazowieckie",
2.30 + "opolskie",
2.31 + "podkarpackie",
2.32 + "podlaskie",
2.33 + "pomorskie",
2.34 + "śląskie",
2.35 + "świętokrzyskie",
2.36 + "warmińsko-mazurskie",
2.37 + "wielkopolskie",
2.38 + "zachodniopomorskie",
2.39 +};
2.40 +
2.41 +static int ggp_pubdir_provinces_count = sizeof(ggp_pubdir_provinces)/sizeof(gchar*);
2.42 +
2.43 /******************************************************************************/
2.44
2.45 void ggp_pubdir_record_free(ggp_pubdir_record *records, int count)
2.46 @@ -95,6 +131,9 @@
2.47 for (i = 0; i < count; i++)
2.48 {
2.49 g_free(records[i].label);
2.50 + g_free(records[i].nickname);
2.51 + g_free(records[i].first_name);
2.52 + g_free(records[i].last_name);
2.53 g_free(records[i].city);
2.54 }
2.55 g_free(records);
2.56 @@ -203,10 +242,10 @@
2.57 while (xml)
2.58 {
2.59 ggp_pubdir_record *record = &records[i++];
2.60 - gchar *label = NULL, *nick = NULL, *name = NULL,
2.61 - *surname = NULL, *city = NULL, *birth_s = NULL;
2.62 + gchar *city = NULL, *birth_s = NULL;
2.63 unsigned int gender = 0;
2.64 - GTimeVal birth_g;
2.65 + const gchar *uin_s;
2.66 +
2.67 g_assert(i <= record_count);
2.68
2.69 record->uin = ggp_str_to_uin(xmlnode_get_attrib(xml, "uin"));
2.70 @@ -215,35 +254,39 @@
2.71 if (record->uin == 0)
2.72 purple_debug_error("gg", "ggp_pubdir_got_data:"
2.73 " invalid uin\n");
2.74 + uin_s = ggp_uin_to_str(record->uin);
2.75
2.76 - ggp_xml_get_string(xml, "label", &label);
2.77 - ggp_xml_get_string(xml, "nick", &nick);
2.78 - ggp_xml_get_string(xml, "name", &name);
2.79 - ggp_xml_get_string(xml, "surname", &surname);
2.80 + ggp_xml_get_string(xml, "label", &record->label);
2.81 + ggp_xml_get_string(xml, "nick", &record->nickname);
2.82 + ggp_xml_get_string(xml, "name", &record->first_name);
2.83 + ggp_xml_get_string(xml, "surname", &record->last_name);
2.84 ggp_xml_get_string(xml, "city", &city);
2.85 ggp_xml_get_string(xml, "birth", &birth_s);
2.86 ggp_xml_get_uint(xml, "gender", &gender);
2.87 ggp_xml_get_uint(xml, "age", &record->age);
2.88 + ggp_xml_get_uint(xml, "province", &record->province);
2.89
2.90 - if (label)
2.91 - record->label = g_strdup(label);
2.92 - else if (nick)
2.93 - record->label = g_strdup(nick);
2.94 - else if (name && surname)
2.95 - record->label = g_strdup_printf("%s %s", name, surname);
2.96 - else if (name)
2.97 - record->label = g_strdup(name);
2.98 - else if (surname)
2.99 - record->label = g_strdup(surname);
2.100 + record->label = ggp_free_if_equal(record->label, uin_s);
2.101 + record->label = ggp_free_if_equal(record->label, "");
2.102 + record->nickname = ggp_free_if_equal(record->nickname, uin_s);
2.103 + record->nickname = ggp_free_if_equal(record->nickname, "");
2.104 + record->first_name = ggp_free_if_equal(record->first_name, "");
2.105 + record->last_name = ggp_free_if_equal(record->last_name, "");
2.106 +
2.107 + if (record->label) {}
2.108 + else if (record->nickname)
2.109 + record->label = g_strdup(record->nickname);
2.110 + else if (record->first_name && record->last_name)
2.111 + record->label = g_strdup_printf("%s %s",
2.112 + record->first_name, record->last_name);
2.113 + else if (record->first_name)
2.114 + record->label = g_strdup(record->first_name);
2.115 + else if (record->last_name)
2.116 + record->label = g_strdup(record->last_name);
2.117 if (record->label)
2.118 g_strstrip(record->label);
2.119 -
2.120 - if (g_strcmp0(record->label, ggp_uin_to_str(record->uin)) == 0 ||
2.121 - g_strcmp0(record->label, "") == 0)
2.122 - {
2.123 - g_free(record->label);
2.124 - record->label = NULL;
2.125 - }
2.126 + if (record->nickname)
2.127 + g_strstrip(record->nickname);
2.128
2.129 if (gender == 1)
2.130 record->gender = GGP_PUBDIR_GENDER_FEMALE;
2.131 @@ -262,18 +305,17 @@
2.132 record->city = NULL;
2.133 }
2.134
2.135 - if (birth_s && g_time_val_from_iso8601(birth_s, &birth_g))
2.136 - record->birth = birth_g.tv_sec;
2.137 + record->birth = ggp_date_from_iso8601(birth_s);
2.138 //TODO: calculate age from birth
2.139
2.140 //TODO: verbose
2.141 - //purple_debug_misc("gg", "ggp_pubdir_got_data: [%d][%s][%s][%d][%d][%lu]\n",
2.142 - // record->uin, record->label, record->city, record->gender, record->age, record->birth);
2.143 + purple_debug_misc("gg", "ggp_pubdir_got_data: [uin:%d] "
2.144 + "[label:%s] [nick:%s] [first name:%s] [last name:%s] "
2.145 + "[city:%s] [gender:%d] [age:%d] [birth:%lu]\n",
2.146 + record->uin, record->label, record->nickname,
2.147 + record->first_name, record->last_name, record->city,
2.148 + record->gender, record->age, record->birth);
2.149
2.150 - g_free(label);
2.151 - g_free(nick);
2.152 - g_free(name);
2.153 - g_free(surname);
2.154 g_free(city);
2.155
2.156 xml = xmlnode_get_next_twin(xml);
2.157 @@ -342,9 +384,15 @@
2.158 _("Message"), status_message);
2.159 }
2.160
2.161 - if (record->label)
2.162 - purple_notify_user_info_add_pair_plaintext(info, _("Name"),
2.163 - record->label);
2.164 + if (record->nickname)
2.165 + purple_notify_user_info_add_pair_plaintext(info,
2.166 + _("Nickname"), record->nickname);
2.167 + if (record->first_name)
2.168 + purple_notify_user_info_add_pair_plaintext(info,
2.169 + _("First name"), record->first_name);
2.170 + if (record->last_name)
2.171 + purple_notify_user_info_add_pair_plaintext(info,
2.172 + _("Last name"), record->last_name);
2.173 if (record->gender != GGP_PUBDIR_GENDER_UNSPECIFIED)
2.174 purple_notify_user_info_add_pair_plaintext(info, _("Gender"),
2.175 record->gender == GGP_PUBDIR_GENDER_FEMALE ?
2.176 @@ -353,14 +401,8 @@
2.177 purple_notify_user_info_add_pair_plaintext(info, _("City"),
2.178 record->city);
2.179 if (record->birth)
2.180 - {
2.181 - GDate date;
2.182 - gchar buff[15];
2.183 - g_date_set_time(&date, record->birth);
2.184 - g_date_strftime(buff, sizeof(buff), "%Y-%m-%d", &date);
2.185 purple_notify_user_info_add_pair_plaintext(info, _("Birthday"),
2.186 - buff);
2.187 - }
2.188 + ggp_date_strftime("%Y-%m-%d", record->birth));
2.189 else if (record->age)
2.190 {
2.191 gchar *age_s = g_strdup_printf("%d", record->age);
2.192 @@ -732,3 +774,191 @@
2.193 ggp_pubdir_search_form *form = _form;
2.194 ggp_pubdir_search(gc, form);
2.195 }
2.196 +
2.197 +/*******************************************************************************
2.198 + * Own profile.
2.199 + ******************************************************************************/
2.200 +
2.201 +void ggp_pubdir_set_info(PurpleConnection *gc)
2.202 +{
2.203 + ggp_pubdir_get_info(gc, ggp_str_to_uin(purple_account_get_username(
2.204 + purple_connection_get_account(gc))),
2.205 + ggp_pubdir_set_info_dialog, NULL);
2.206 +}
2.207 +
2.208 +static void ggp_pubdir_set_info_dialog(PurpleConnection *gc, int records_count,
2.209 + const ggp_pubdir_record *records, int next_offset, void *user_data)
2.210 +{
2.211 + PurpleRequestFields *fields;
2.212 + PurpleRequestFieldGroup *group;
2.213 + PurpleRequestField *field;
2.214 + int default_gender, i;
2.215 + const ggp_pubdir_record *record;
2.216 +
2.217 + purple_debug_info("gg", "ggp_pubdir_set_info_dialog (record: %d)\n",
2.218 + records_count);
2.219 +
2.220 + record = (records_count == 1 ? &records[0] : NULL);
2.221 +
2.222 + fields = purple_request_fields_new();
2.223 + group = purple_request_field_group_new(NULL);
2.224 + purple_request_fields_add_group(fields, group);
2.225 +
2.226 + field = purple_request_field_string_new("first_name", _("First name"),
2.227 + record ? record->first_name : NULL, FALSE);
2.228 + purple_request_field_group_add_field(group, field);
2.229 +
2.230 + field = purple_request_field_string_new("last_name", _("Last name"),
2.231 + record ? record->last_name : NULL, FALSE);
2.232 + purple_request_field_group_add_field(group, field);
2.233 +
2.234 + default_gender = -1;
2.235 + if (record && record->gender == GGP_PUBDIR_GENDER_MALE)
2.236 + default_gender = 0;
2.237 + else if (record && record->gender == GGP_PUBDIR_GENDER_FEMALE)
2.238 + default_gender = 1;
2.239 +
2.240 + field = purple_request_field_choice_new("gender", _("Gender"),
2.241 + default_gender);
2.242 + purple_request_field_set_required(field, TRUE);
2.243 + purple_request_field_choice_add(field, _("Male"));
2.244 + purple_request_field_choice_add(field, _("Female"));
2.245 + purple_request_field_group_add_field(group, field);
2.246 +
2.247 + field = purple_request_field_string_new("birth_date", _("Birth Day"),
2.248 + (record && record->birth) ?
2.249 + ggp_date_strftime("%Y-%m-%d", record->birth) : NULL, FALSE);
2.250 + purple_request_field_set_required(field, TRUE);
2.251 + purple_request_field_group_add_field(group, field);
2.252 +
2.253 + field = purple_request_field_string_new("city", _("City"),
2.254 + record ? record->city : NULL, FALSE);
2.255 + purple_request_field_group_add_field(group, field);
2.256 +
2.257 + field = purple_request_field_choice_new("province", _("Voivodeship"), 0);
2.258 + purple_request_field_group_add_field(group, field);
2.259 + purple_request_field_choice_add(field, _("Not specified"));
2.260 + for (i = 0; i < ggp_pubdir_provinces_count; i++)
2.261 + {
2.262 + purple_request_field_choice_add(field, ggp_pubdir_provinces[i]);
2.263 + if (record && i + 1 == record->province)
2.264 + {
2.265 + purple_request_field_choice_set_value(field, i + 1);
2.266 + purple_request_field_choice_set_default_value(field,
2.267 + i + 1); // TODO: libpurple bug?
2.268 + }
2.269 + }
2.270 +
2.271 + purple_request_fields(gc, _("Set User Info"), _("Set User Info"),
2.272 + NULL, fields,
2.273 + _("OK"), G_CALLBACK(ggp_pubdir_set_info_request),
2.274 + _("Cancel"), NULL,
2.275 + purple_connection_get_account(gc), NULL, NULL, gc);
2.276 +
2.277 +}
2.278 +
2.279 +static void ggp_pubdir_set_info_request(PurpleConnection *gc,
2.280 + PurpleRequestFields *fields)
2.281 +{
2.282 + gchar *url;
2.283 + uin_t uin = ggp_str_to_uin(purple_account_get_username(
2.284 + purple_connection_get_account(gc)));
2.285 + ggp_pubdir_record *record = g_new0(ggp_pubdir_record, 1);
2.286 + gchar *birth_s;
2.287 +
2.288 + purple_debug_info("gg", "ggp_pubdir_set_info_request\n");
2.289 +
2.290 + record->uin = uin;
2.291 + record->first_name = g_strdup(purple_request_fields_get_string(fields,
2.292 + "first_name"));
2.293 + record->last_name = g_strdup(purple_request_fields_get_string(fields,
2.294 + "last_name"));
2.295 + if (purple_request_fields_get_choice(fields, "gender") == 0)
2.296 + record->gender = GGP_PUBDIR_GENDER_MALE;
2.297 + else
2.298 + record->gender = GGP_PUBDIR_GENDER_FEMALE;
2.299 + record->city = g_strdup(purple_request_fields_get_string(fields,
2.300 + "city"));
2.301 + record->province = purple_request_fields_get_choice(fields, "province");
2.302 +
2.303 + birth_s = g_strdup_printf("%sT10:00:00+00:00",
2.304 + purple_request_fields_get_string(fields, "birth_date"));
2.305 + record->birth = ggp_date_from_iso8601(birth_s);
2.306 + g_free(birth_s);
2.307 + purple_debug_info("gg", "ggp_pubdir_set_info_request: birth [%lu][%s]\n",
2.308 + record->birth, purple_request_fields_get_string(
2.309 + fields, "birth_date"));
2.310 +
2.311 + url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u.xml", uin);
2.312 + ggp_oauth_request(gc, ggp_pubdir_set_info_got_token, record,
2.313 + "PUT", url);
2.314 + g_free(url);
2.315 +}
2.316 +
2.317 +static void ggp_pubdir_set_info_got_token(PurpleConnection *gc,
2.318 + const gchar *token, gpointer _record)
2.319 +{
2.320 + ggp_pubdir_record *record = _record;
2.321 + gchar *request, *request_data, *url;
2.322 + gchar *name, *surname, *city;
2.323 + uin_t uin = record->uin;
2.324 +
2.325 + if (!token || !PURPLE_CONNECTION_IS_VALID(gc))
2.326 + {
2.327 + // TODO: notify about failure
2.328 + ggp_pubdir_record_free(record, 1);
2.329 + return;
2.330 + }
2.331 +
2.332 + name = g_uri_escape_string(record->first_name, NULL, FALSE);
2.333 + surname = g_uri_escape_string(record->last_name, NULL, FALSE);
2.334 + city = g_uri_escape_string(record->city, NULL, FALSE);
2.335 +
2.336 + request_data = g_strdup_printf(
2.337 + "name=%s&"
2.338 + "surname=%s&"
2.339 + "birth=%sT10:00:00%%2B00:00&"
2.340 + "birth_priv=2&"
2.341 + "gender=%d&"
2.342 + "gender_priv=2&"
2.343 + "city=%s&"
2.344 + "province=%d",
2.345 + name, surname,
2.346 + ggp_date_strftime("%Y-%m-%d", record->birth),
2.347 + record->gender,
2.348 + city,
2.349 + record->province);
2.350 +
2.351 + //TODO: verbose
2.352 + //purple_debug_misc("gg", "ggp_pubdir_set_info_got_token: query [%s]\n",
2.353 + // request_data);
2.354 +
2.355 + url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u.xml", uin);
2.356 + request = g_strdup_printf(
2.357 + "PUT /users/%u.xml HTTP/1.1\r\n"
2.358 + "Host: api.gadu-gadu.pl\r\n"
2.359 + "%s\r\n"
2.360 + "Content-Length: %d\r\n"
2.361 + "Content-Type: application/x-www-form-urlencoded\r\n"
2.362 + "\r\n%s",
2.363 + uin, token, strlen(request_data), request_data);
2.364 +
2.365 + purple_util_fetch_url_request(purple_connection_get_account(gc), url,
2.366 + FALSE, NULL, TRUE, request, FALSE, -1,
2.367 + ggp_pubdir_set_info_got_response, NULL);
2.368 +
2.369 + g_free(request);
2.370 + g_free(request_data);
2.371 + g_free(url);
2.372 + ggp_pubdir_record_free(record, 1);
2.373 +}
2.374 +
2.375 +static void ggp_pubdir_set_info_got_response(PurpleUtilFetchUrlData *url_data,
2.376 + gpointer user_data, const gchar *url_text, gsize len,
2.377 + const gchar *error_message)
2.378 +{
2.379 + purple_debug_info("gg", "ggp_pubdir_set_info_got_response: [%s]\n", url_text);
2.380 + //<result><status>0</status></result>
2.381 +
2.382 + //TODO: notify about failure
2.383 +}
3.1 --- a/libpurple/protocols/gg/pubdir-prpl.h
3.2 +++ b/libpurple/protocols/gg/pubdir-prpl.h
3.3 @@ -15,8 +15,12 @@
3.4 {
3.5 uin_t uin;
3.6 gchar *label;
3.7 + gchar *nickname;
3.8 + gchar *first_name;
3.9 + gchar *last_name;
3.10 ggp_pubdir_gender gender;
3.11 gchar *city;
3.12 + unsigned int province;
3.13 time_t birth;
3.14 unsigned int age;
3.15 } ggp_pubdir_record;
3.16 @@ -35,4 +39,6 @@
3.17 void ggp_pubdir_search(PurpleConnection *gc,
3.18 const ggp_pubdir_search_form *form);
3.19
3.20 +void ggp_pubdir_set_info(PurpleConnection *gc);
3.21 +
3.22 #endif /* _GGP_PUBDIR_PRPL_H */
4.1 --- a/libpurple/protocols/gg/utils.c
4.2 +++ b/libpurple/protocols/gg/utils.c
4.3 @@ -209,3 +209,35 @@
4.4 }
4.5 return list;
4.6 }
4.7 +
4.8 +gchar * ggp_free_if_equal(gchar *str, const gchar *pattern)
4.9 +{
4.10 + if (g_strcmp0(str, pattern) == 0)
4.11 + {
4.12 + g_free(str);
4.13 + return NULL;
4.14 + }
4.15 + return str;
4.16 +}
4.17 +
4.18 +const gchar * ggp_date_strftime(const gchar *format, time_t date)
4.19 +{
4.20 + GDate g_date;
4.21 + static gchar buff[30];
4.22 +
4.23 + g_date_set_time(&g_date, date);
4.24 + if (0 == g_date_strftime(buff, sizeof(buff), format, &g_date))
4.25 + return NULL;
4.26 + return buff;
4.27 +}
4.28 +
4.29 +time_t ggp_date_from_iso8601(const gchar *str)
4.30 +{
4.31 + GTimeVal g_timeval;
4.32 +
4.33 + if (!str)
4.34 + return 0;
4.35 + if (!g_time_val_from_iso8601(str, &g_timeval))
4.36 + return 0;
4.37 + return g_timeval.tv_sec;
4.38 +}
5.1 --- a/libpurple/protocols/gg/utils.h
5.2 +++ b/libpurple/protocols/gg/utils.h
5.3 @@ -82,4 +82,10 @@
5.4
5.5 GList * ggp_list_truncate(GList *list, gint length, GDestroyNotify free_func);
5.6
5.7 +gchar * ggp_free_if_equal(gchar *str, const gchar *pattern);
5.8 +
5.9 +const gchar * ggp_date_strftime(const gchar *format, time_t date);
5.10 +
5.11 +time_t ggp_date_from_iso8601(const gchar *str);
5.12 +
5.13 #endif /* _GGP_UTILS_H */