comparison libpurple/protocols/mxit/actions.c @ 28526:69aa4660401a

Initial addition of the MXit protocol plugin, provided by the MXit folks themselves.
author John Bailey <rekkanoryo@rekkanoryo.org>
date Sun, 08 Nov 2009 23:55:56 +0000
parents
children 0fd6d016c474
comparison
equal deleted inserted replaced
28525:13e668ef158d 28526:69aa4660401a
1 /*
2 * MXit Protocol libPurple Plugin
3 *
4 * -- handle MXit plugin actions --
5 *
6 * Pieter Loubser <libpurple@mxit.com>
7 *
8 * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
9 * <http://www.mxitlifestyle.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "purple.h"
32
33 #include "protocol.h"
34 #include "mxit.h"
35 #include "roster.h"
36 #include "actions.h"
37 #include "splashscreen.h"
38 #include "cipher.h"
39 #include "profile.h"
40
41
42 /* MXit Moods */
43 static const char* moods[] = {
44 /* 0 */ "None",
45 /* 1 */ "Angry",
46 /* 2 */ "Excited",
47 /* 3 */ "Grumpy",
48 /* 4 */ "Happy",
49 /* 5 */ "In Love",
50 /* 6 */ "Invincible",
51 /* 7 */ "Sad",
52 /* 8 */ "Hot",
53 /* 9 */ "Sick",
54 /* 10 */ "Sleepy"
55 };
56
57
58 /*------------------------------------------------------------------------
59 * The user has selected to change their current mood.
60 *
61 * @param gc The connection object
62 * @param fields The fields from the request pop-up
63 */
64 static void mxit_cb_set_mood( PurpleConnection* gc, PurpleRequestFields* fields )
65 {
66 struct MXitSession* session = (struct MXitSession*) gc->proto_data;
67 int mood = purple_request_fields_get_choice( fields, "mood" );
68
69 purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_set_mood (%i)\n", mood );
70
71 if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
72 purple_debug_error( MXIT_PLUGIN_ID, "Unable to set mood; account offline.\n" );
73 return;
74 }
75
76 /* Save the new mood in session */
77 session->mood = mood;
78
79 /* now send the update to MXit */
80 mxit_send_mood( session, mood );
81 }
82
83
84 /*------------------------------------------------------------------------
85 * Create and display the mood selection window to the user.
86 *
87 * @param action The action object
88 */
89 static void mxit_cb_action_mood( PurplePluginAction* action )
90 {
91 PurpleConnection* gc = (PurpleConnection*) action->context;
92 struct MXitSession* session = (struct MXitSession*) gc->proto_data;
93
94 PurpleRequestFields* fields = NULL;
95 PurpleRequestFieldGroup* group = NULL;
96 PurpleRequestField* field = NULL;
97 unsigned int i = 0;
98
99 purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_action_mood\n" );
100
101 fields = purple_request_fields_new();
102 group = purple_request_field_group_new( NULL );
103 purple_request_fields_add_group( fields, group );
104
105 /* show current mood */
106 field = purple_request_field_string_new( "current", _( "Current Mood" ), _( moods[session->mood] ), FALSE );
107 purple_request_field_string_set_editable( field, FALSE ); /* current mood field is not editable */
108 purple_request_field_group_add_field( group, field );
109
110 /* add all moods to list */
111 field = purple_request_field_choice_new( "mood", _( "New Mood" ), 0 );
112 for ( i = 0; i < ARRAY_SIZE( moods ); i++ ) {
113 purple_request_field_choice_add( field, _( moods[i] ) );
114 }
115 purple_request_field_set_required( field, TRUE );
116 purple_request_field_choice_set_default_value( field, session->mood );
117 purple_request_field_group_add_field( group, field );
118
119 /* (reference: "libpurple/request.h") */
120 purple_request_fields( gc, _( "Mood" ), _( "Change your Mood" ), _( "How do you feel right now?" ), fields, _( "Set" ),
121 G_CALLBACK( mxit_cb_set_mood ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
122 }
123
124
125 /*------------------------------------------------------------------------
126 * The user has selected to change their profile.
127 *
128 * @param gc The connection object
129 * @param fields The fields from the request pop-up
130 */
131 static void mxit_cb_set_profile( PurpleConnection* gc, PurpleRequestFields* fields )
132 {
133 struct MXitSession* session = (struct MXitSession*) gc->proto_data;
134 PurpleRequestField* field = NULL;
135 const char* pin = NULL;
136 const char* pin2 = NULL;
137 const char* name = NULL;
138 const char* bday = NULL;
139 const char* err = NULL;
140 int len;
141 int i;
142
143 purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_set_profile\n" );
144
145 if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
146 purple_debug_error( MXIT_PLUGIN_ID, "Unable to update profile; account offline.\n" );
147 return;
148 }
149
150 /* validate pin */
151 pin = purple_request_fields_get_string( fields, "pin" );
152 if ( !pin ) {
153 err = "The PIN you entered is invalid.";
154 goto out;
155 }
156 len = strlen( pin );
157 if ( ( len < 4 ) || ( len > 10 ) ) {
158 err = "The PIN you entered has an invalid length [4-10].";
159 goto out;
160 }
161 for ( i = 0; i < len; i++ ) {
162 if ( !g_ascii_isdigit( pin[i] ) ) {
163 err = "The PIN is invalid. It should only consist of digits [0-9].";
164 goto out;
165 }
166 }
167 pin2 = purple_request_fields_get_string( fields, "pin2" );
168 if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) {
169 err = "The two PINs you entered does not match.";
170 goto out;
171 }
172
173 /* validate name */
174 name = purple_request_fields_get_string( fields, "name" );
175 if ( ( !name ) || ( strlen( name ) < 3 ) ) {
176 err = "The name you entered is invalid.";
177 goto out;
178 }
179
180 /* validate birthdate */
181 bday = purple_request_fields_get_string( fields, "bday" );
182 if ( ( !bday ) || ( strlen( bday ) < 10 ) || ( !validateDate( bday ) ) ) {
183 err = "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'.";
184 goto out;
185 }
186
187 out:
188 if ( !err ) {
189 struct MXitProfile* profile = session->profile;
190 GString* attributes = g_string_sized_new( 128 );
191 char attrib[512];
192 unsigned int acount = 0;
193
194 /* all good, so we can now update the profile */
195
196 /* update pin */
197 purple_account_set_password( session->acc, pin );
198 g_free( session->encpwd );
199 session->encpwd = mxit_encrypt_password( session );
200
201 /* update name */
202 g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) );
203 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROF_TYPE_UTF8, profile->nickname );
204 g_string_append( attributes, attrib );
205 acount++;
206
207 /* update hidden */
208 field = purple_request_fields_get_field( fields, "hidden" );
209 profile->hidden = purple_request_field_bool_get_value( field );
210 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROF_TYPE_BOOL, ( profile->hidden ) ? "1" : "0" );
211 g_string_append( attributes, attrib );
212 acount++;
213
214 /* update birthday */
215 strcpy( profile->birthday, bday );
216 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROF_TYPE_UTF8, profile->birthday );
217 g_string_append( attributes, attrib );
218 acount++;
219
220 /* update gender */
221 if ( purple_request_fields_get_choice( fields, "male" ) == 0 )
222 profile->male = FALSE;
223 else
224 profile->male = TRUE;
225 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROF_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
226 g_string_append( attributes, attrib );
227 acount++;
228
229 /* update title */
230 name = purple_request_fields_get_string( fields, "title" );
231 if ( !name )
232 profile->title[0] = '\0';
233 else
234 strcpy( profile->title, name );
235 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROF_TYPE_UTF8, profile->title );
236 g_string_append( attributes, attrib );
237 acount++;
238
239 /* update firstname */
240 name = purple_request_fields_get_string( fields, "firstname" );
241 if ( !name )
242 profile->firstname[0] = '\0';
243 else
244 strcpy( profile->firstname, name );
245 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROF_TYPE_UTF8, profile->firstname );
246 g_string_append( attributes, attrib );
247 acount++;
248
249 /* update lastname */
250 name = purple_request_fields_get_string( fields, "lastname" );
251 if ( !name )
252 profile->lastname[0] = '\0';
253 else
254 strcpy( profile->lastname, name );
255 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROF_TYPE_UTF8, profile->lastname );
256 g_string_append( attributes, attrib );
257 acount++;
258
259 /* update email address */
260 name = purple_request_fields_get_string( fields, "email" );
261 if ( !name )
262 profile->email[0] = '\0';
263 else
264 strcpy( profile->email, name );
265 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROF_TYPE_UTF8, profile->email );
266 g_string_append( attributes, attrib );
267 acount++;
268
269 /* update mobile number */
270 name = purple_request_fields_get_string( fields, "mobilenumber" );
271 if ( !name )
272 profile->mobilenr[0] = '\0';
273 else
274 strcpy( profile->mobilenr, name );
275 g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROF_TYPE_UTF8, profile->mobilenr );
276 g_string_append( attributes, attrib );
277 acount++;
278
279 /* send the profile update to MXit */
280 mxit_send_extprofile_update( session, session->encpwd, acount, attributes->str );
281 g_string_free( attributes, TRUE );
282 }
283 else {
284 /* show error to user */
285 mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Profile Update Error" ), _( err ) );
286 }
287 }
288
289
290 /*------------------------------------------------------------------------
291 * Display and update the user's profile.
292 *
293 * @param action The action object
294 */
295 static void mxit_cb_action_profile( PurplePluginAction* action )
296 {
297 PurpleConnection* gc = (PurpleConnection*) action->context;
298 struct MXitSession* session = (struct MXitSession*) gc->proto_data;
299 struct MXitProfile* profile = session->profile;
300
301 PurpleRequestFields* fields = NULL;
302 PurpleRequestFieldGroup* group = NULL;
303 PurpleRequestField* field = NULL;
304
305 purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_action_profile\n" );
306
307 /* ensure that we actually have the user's profile information */
308 if ( !profile ) {
309 /* no profile information yet, so we cannot update */
310 mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile" ), _( "Your profile information is not yet retrieved. Please try again later." ) );
311 return;
312 }
313
314 fields = purple_request_fields_new();
315 group = purple_request_field_group_new( NULL );
316 purple_request_fields_add_group( fields, group );
317
318 /* pin */
319 field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
320 purple_request_field_string_set_masked( field, TRUE );
321 purple_request_field_group_add_field( group, field );
322 field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE );
323 purple_request_field_string_set_masked( field, TRUE );
324 purple_request_field_group_add_field( group, field );
325
326 /* display name */
327 field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE );
328 purple_request_field_group_add_field( group, field );
329
330 /* birthday */
331 field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
332 purple_request_field_group_add_field( group, field );
333
334 /* gender */
335 field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
336 purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */
337 purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */
338 purple_request_field_group_add_field( group, field );
339
340 /* hidden */
341 field = purple_request_field_bool_new( "hidden", _( "Hide my number" ), profile->hidden );
342 purple_request_field_group_add_field( group, field );
343
344 /* title */
345 field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE );
346 purple_request_field_group_add_field( group, field );
347
348 /* first name */
349 field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE );
350 purple_request_field_group_add_field( group, field );
351
352 /* last name */
353 field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE );
354 purple_request_field_group_add_field( group, field );
355
356 /* email */
357 field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE );
358 purple_request_field_group_add_field( group, field );
359
360 /* mobile number */
361 field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE );
362 purple_request_field_group_add_field( group, field );
363
364 /* (reference: "libpurple/request.h") */
365 purple_request_fields( gc, _( "Profile" ), _( "Update your Profile" ), _( "Here you can update your MXit profile" ), fields, _( "Set" ),
366 G_CALLBACK( mxit_cb_set_profile ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
367 }
368
369
370 /*------------------------------------------------------------------------
371 * Display the current splash-screen, or a notification pop-up if one is not available.
372 *
373 * @param action The action object
374 */
375 static void mxit_cb_action_splash( PurplePluginAction* action )
376 {
377 PurpleConnection* gc = (PurpleConnection*) action->context;
378 struct MXitSession* session = (struct MXitSession*) gc->proto_data;
379
380 if ( splash_current( session ) != NULL )
381 splash_display( session );
382 else
383 mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "View Splash" ), _( "There is no splash-screen currently available" ) );
384 }
385
386
387 /*------------------------------------------------------------------------
388 * Display info about the plugin.
389 *
390 * @param action The action object
391 */
392 static void mxit_cb_action_about( PurplePluginAction* action )
393 {
394 char version[256];
395
396 g_snprintf( version, sizeof( version ), "MXit libPurple Plugin v%s\n"
397 "MXit Client Protocol v%s\n\n"
398 "Author:\nPieter Loubser\n\n"
399 "Contributors:\nAndrew Victor\n\n"
400 "Testers:\nBraeme Le Roux\n\n",
401 MXIT_PLUGIN_VERSION, MXIT_CP_RELEASE );
402
403 mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "About" ), version );
404 }
405
406
407 /*------------------------------------------------------------------------
408 * Associate actions with the MXit plugin.
409 *
410 * @param plugin The MXit protocol plugin
411 * @param context The connection context (if available)
412 * @return The list of plugin actions
413 */
414 GList* mxit_actions( PurplePlugin* plugin, gpointer context )
415 {
416 PurplePluginAction* action = NULL;
417 GList* m = NULL;
418
419 /* display / change mood */
420 action = purple_plugin_action_new( _( "Change Mood..." ), mxit_cb_action_mood );
421 m = g_list_append( m, action );
422
423 /* display / change profile */
424 action = purple_plugin_action_new( _( "Change Profile..." ), mxit_cb_action_profile );
425 m = g_list_append( m, action );
426
427 /* display splash-screen */
428 action = purple_plugin_action_new( _( "View Splash..." ), mxit_cb_action_splash );
429 m = g_list_append( m, action );
430
431 /* display plugin version */
432 action = purple_plugin_action_new( _( "About..." ), mxit_cb_action_about );
433 m = g_list_append( m, action );
434
435 return m;
436 }
437