pidgin/pidgin

Use gchar for xdg dirs variables
xdg-dirs
2017-06-30, qarkai
d2408369eb7c
Use gchar for xdg dirs variables
/*
* MXit Protocol libPurple Plugin
*
* -- user profile's --
*
* Andrew Victor <libpurple@mxit.com>
*
* (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
* <http://www.mxitlifestyle.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#define _XOPEN_SOURCE 1
#include <time.h>
#include "internal.h"
#include "image-store.h"
#include "mxit.h"
#include "profile.h"
#include "roster.h"
/*------------------------------------------------------------------------
* Return the MXit Relationship status as a string.
*
* @param id The Relationship status value (see profile.h)
* @return The relationship status as a text string.
*/
const char* mxit_relationship_to_name( short id )
{
switch ( id ) {
case MXIT_RELATIONSHIP_UNKNOWN :
return _( "Unknown" );
case MXIT_RELATIONSHIP_DONTSAY :
return _( "Don't want to say" );
case MXIT_RELATIONSHIP_SINGLE :
return _( "Single" );
case MXIT_RELATIONSHIP_INVOLVED :
return _( "In a relationship" );
case MXIT_RELATIONSHIP_ENGAGED :
return _( "Engaged" );
case MXIT_RELATIONSHIP_MARRIED :
return _( "Married" );
case MXIT_RELATIONSHIP_COMPLICATED :
return _( "It's complicated" );
case MXIT_RELATIONSHIP_WIDOWED :
return _( "Widowed" );
case MXIT_RELATIONSHIP_SEPARATED :
return _( "Separated" );
case MXIT_RELATIONSHIP_DIVORCED :
return _( "Divorced" );
default :
return "";
}
}
/*------------------------------------------------------------------------
* Returns true if it is a valid date.
*
* @param bday Date-of-Birth string (YYYY-MM-DD)
* @return TRUE if valid, else FALSE
*/
gboolean validateDate( const char* bday )
{
struct tm* tm;
time_t t;
int cur_year;
int max_days[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char date[16];
int year;
int month;
int day;
/* validate length */
if ( strlen( bday ) != 10 ) {
return FALSE;
}
/* validate the format */
if ( ( !isdigit( bday[0] ) ) || ( !isdigit( bday[1] ) ) || ( !isdigit( bday[2] ) ) || ( !isdigit( bday[3] ) ) || /* year */
( bday[4] != '-' ) ||
( !isdigit( bday[5] ) ) || ( !isdigit( bday[6] ) ) || /* month */
( bday[7] != '-' ) ||
( !isdigit( bday[8] ) ) || ( !isdigit( bday[9] ) ) ) { /* day */
return FALSE;
}
/* convert */
t = time( NULL );
tm = gmtime( &t );
cur_year = tm->tm_year + 1900;
memcpy( date, bday, 10 );
date[4] = '\0';
date[7] = '\0';
date[10] = '\0';
year = atoi( &date[0] );
month = atoi( &date[5] );
day = atoi( &date[8] );
/* validate month */
if ( ( month < 1 ) || ( month > 12 ) ) {
return FALSE;
}
/* validate day */
if ( ( day < 1 ) || ( day > max_days[month] ) ) {
return FALSE;
}
/* validate year */
if ( ( year < ( cur_year - 100 ) ) || ( year >= cur_year ) ) {
/* you are either tooo old or tooo young to join mxit... sorry */
return FALSE;
}
/* special case leap-year */
if ( ( year % 4 != 0 ) && ( month == 2 ) && ( day == 29 ) ) {
/* cannot have 29 days in February in non leap-years! */
return FALSE;
}
return TRUE;
}
/*------------------------------------------------------------------------
* Calculate an Age from the date-of-birth.
*
* @param date Date-of-Birth string (YYYY-MM-DD)
* @return The age
*/
static int calculateAge( const char* date )
{
time_t t;
struct tm now, bdate;
int age;
if ( ( !date ) || ( !*date ) )
return 0;
/* current time */
t = time( NULL );
localtime_r( &t, &now );
/* decode hdate */
memset( &bdate, 0, sizeof( struct tm ) );
purple_str_to_time( date, FALSE, &bdate, NULL, NULL );
/* calculate difference */
age = now.tm_year - bdate.tm_year;
if ( now.tm_mon < bdate.tm_mon ) /* is before month of birth */
age--;
else if ( ( now.tm_mon == bdate.tm_mon ) && ( now.tm_mday < bdate.tm_mday ) ) /* before birthday in current month */
age--;
return age;
}
/*------------------------------------------------------------------------
* Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS)
*
* @param msecs The timestamps (milliseconds since epoch)
* @return Date & Time in a display'able format.
*/
static const char* datetime( gint64 msecs )
{
time_t secs = msecs / 1000;
struct tm t;
localtime_r( &secs, &t );
return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
}
/*------------------------------------------------------------------------
* Display the profile information.
*
* @param session The MXit session object
* @param username The username who's profile information this is
* @param profile The profile
*/
void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile )
{
PurpleNotifyUserInfo* info = purple_notify_user_info_new();
struct contact* contact = NULL;
PurpleBuddy* buddy;
gchar* tmp = NULL;
buddy = purple_blist_find_buddy( session->acc, username );
if ( buddy ) {
purple_notify_user_info_add_pair_plaintext( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
purple_notify_user_info_add_section_break( info );
contact = purple_buddy_get_protocol_data( buddy );
}
purple_notify_user_info_add_pair_plaintext( info, _( "Display Name" ), profile->nickname );
tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) );
purple_notify_user_info_add_pair_plaintext( info, _( "Birthday" ), tmp );
g_free( tmp );
purple_notify_user_info_add_pair_plaintext( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
/* optional information */
purple_notify_user_info_add_pair_plaintext( info, _( "First Name" ), profile->firstname );
purple_notify_user_info_add_pair_plaintext( info, _( "Last Name" ), profile->lastname );
purple_notify_user_info_add_pair_plaintext( info, _( "Country" ), profile->regcountry );
if ( *profile->aboutme )
purple_notify_user_info_add_pair_plaintext( info, _( "About Me" ), profile->aboutme );
if ( *profile->whereami )
purple_notify_user_info_add_pair_plaintext( info, _( "Where I Live" ), profile->whereami );
purple_notify_user_info_add_pair_plaintext( info, _( "Relationship Status" ), mxit_relationship_to_name( profile->relationship ) );
purple_notify_user_info_add_section_break( info );
if ( contact ) {
/* presence */
purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
/* last online */
if ( contact->presence == MXIT_PRESENCE_OFFLINE )
purple_notify_user_info_add_pair_plaintext( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
/* mood */
if ( contact->mood != MXIT_MOOD_NONE )
purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
else
purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), _( "None" ) );
/* status message */
if ( contact->statusMsg ) {
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg );
}
/* subscription type */
purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
}
else {
/* this is an invite */
contact = get_mxit_invite_contact( session, username );
if ( contact ) {
/* invite found */
if ( contact->msg )
purple_notify_user_info_add_pair_plaintext( info, _( "Invite Message" ), contact->msg );
if (contact->image) {
/* this invite has a avatar */
char* img_text;
guint img_id;
img_id = purple_image_store_add_temporary(contact->image);
img_text = g_strdup_printf("<img src=\""
PURPLE_IMAGE_STORE_PROTOCOL "%u\">", img_id);
purple_notify_user_info_add_pair_html( info, _( "Photo" ), img_text );
g_free( img_text );
}
if ( contact->statusMsg ) {
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg );
}
}
}
purple_notify_userinfo( session->con, username, info, NULL, NULL );
purple_notify_user_info_destroy( info );
}
/*------------------------------------------------------------------------
* Display the profiles of search results.
*
* @param gc The connection object
* @param row The selected row from search-results
* @param user_data NULL (unused)
*/
static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data )
{
/* display add buddy dialog */
purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) );
}
/*------------------------------------------------------------------------
* Display the profiles of search results.
*
* @param session The MXit session object
* @param searchType The type of search (CP_SUGGEST_*)
* @param maxResults The maximum number of results
* @param entries The list of profile entries
*/
void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries )
{
PurpleNotifySearchResults* results;
PurpleNotifySearchColumn* column;
gchar* text;
if ( !entries ) {
mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "No results" ), _( "No contacts found." ) );
return;
}
results = purple_notify_searchresults_new();
if ( !results )
return;
/* define columns */
column = purple_notify_searchresults_column_new( _( "UserId" ) );
purple_notify_searchresult_column_set_visible( column, FALSE );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "Display Name" ) );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "First Name" ) );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "Last Name" ) );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "Gender" ) );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "Age" ) );
purple_notify_searchresults_column_add( results, column );
column = purple_notify_searchresults_column_new( _( "Where I live" ) );
purple_notify_searchresults_column_add( results, column );
while ( entries != NULL ) {
struct MXitProfile* profile = ( struct MXitProfile *) entries->data;
GList* row;
gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) );
/* column values */
row = g_list_append( NULL, g_strdup_printf( "#%s", tmp ) );
row = g_list_append( row, g_strdup( profile->nickname ) );
row = g_list_append( row, g_strdup( profile->firstname ) );
row = g_list_append( row, g_strdup( profile->lastname ) );
row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) );
row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) );
row = g_list_append( row, g_strdup( profile->whereami ) );
purple_notify_searchresults_row_add( results, row );
entries = g_list_next( entries );
g_free( tmp );
}
/* button */
purple_notify_searchresults_button_add( results, PURPLE_NOTIFY_BUTTON_INVITE, mxit_search_results_add_cb );
if ( searchType == CP_SUGGEST_FRIENDS )
text = g_strdup_printf( dngettext( PACKAGE, "You have %i suggested friend.", "You have %i suggested friends.", maxResults ), maxResults );
else
text = g_strdup_printf( dngettext( PACKAGE, "We found %i contact that matches your search.", "We found %i contacts that match your search.", maxResults ), maxResults );
purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL );
g_free( text );
}