pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
More error logging, please.
release-2.x.y
2014-01-18, Mark Doliner
956f247148db
More error logging, please.
/**
* @file state.c State functions and definitions
*
* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* 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
*/
#include
"internal.h"
#include
"debug.h"
#include
"core.h"
#include
"notification.h"
#include
"state.h"
static
const
char
*
away_text
[]
=
{
N_
(
"Available"
),
N_
(
"Available"
),
N_
(
"Busy"
),
N_
(
"Idle"
),
N_
(
"Be Right Back"
),
N_
(
"Away From Computer"
),
N_
(
"On The Phone"
),
N_
(
"Out To Lunch"
),
N_
(
"Available"
),
N_
(
"Available"
)
};
/*
* WLM media PSM info build prcedure
*
* Result can like:
* <CurrentMedia>\0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0</CurrentMedia>\
* <CurrentMedia>\0Games\01\0Playing {0}\0Game Name\0</CurrentMedia>\
* <CurrentMedia>\0Office\01\0Office Message\0Office App Name\0</CurrentMedia>"
*/
static
char
*
msn_build_psm
(
const
char
*
psmstr
,
const
char
*
mediastr
,
const
char
*
guidstr
,
guint
protocol_ver
)
{
xmlnode
*
dataNode
,
*
psmNode
,
*
mediaNode
,
*
guidNode
;
char
*
result
;
int
length
;
dataNode
=
xmlnode_new
(
"Data"
);
psmNode
=
xmlnode_new
(
"PSM"
);
if
(
psmstr
!=
NULL
){
xmlnode_insert_data
(
psmNode
,
psmstr
,
-1
);
}
xmlnode_insert_child
(
dataNode
,
psmNode
);
mediaNode
=
xmlnode_new
(
"CurrentMedia"
);
if
(
mediastr
!=
NULL
){
xmlnode_insert_data
(
mediaNode
,
mediastr
,
-1
);
}
xmlnode_insert_child
(
dataNode
,
mediaNode
);
guidNode
=
xmlnode_new
(
"MachineGuid"
);
if
(
guidstr
!=
NULL
){
xmlnode_insert_data
(
guidNode
,
guidstr
,
-1
);
}
xmlnode_insert_child
(
dataNode
,
guidNode
);
if
(
protocol_ver
>=
16
)
{
/* TODO: What is this for? */
xmlnode
*
ddpNode
=
xmlnode_new
(
"DDP"
);
xmlnode_insert_child
(
dataNode
,
ddpNode
);
}
result
=
xmlnode_to_str
(
dataNode
,
&
length
);
xmlnode_free
(
dataNode
);
return
result
;
}
/* get the CurrentMedia info from the XML node */
char
*
msn_get_currentmedia
(
xmlnode
*
payloadNode
)
{
xmlnode
*
currentmediaNode
;
char
*
currentmedia
;
purple_debug_info
(
"msn"
,
"Get CurrentMedia
\n
"
);
currentmediaNode
=
xmlnode_get_child
(
payloadNode
,
"CurrentMedia"
);
if
(
currentmediaNode
==
NULL
)
{
purple_debug_info
(
"msn"
,
"No CurrentMedia Node
\n
"
);
return
NULL
;
}
currentmedia
=
xmlnode_get_data
(
currentmediaNode
);
return
currentmedia
;
}
/* Get the PSM info from the XML node */
char
*
msn_get_psm
(
xmlnode
*
payloadNode
)
{
xmlnode
*
psmNode
;
char
*
psm
;
purple_debug_info
(
"msn"
,
"msn get PSM
\n
"
);
psmNode
=
xmlnode_get_child
(
payloadNode
,
"PSM"
);
if
(
psmNode
==
NULL
)
{
purple_debug_info
(
"msn"
,
"No PSM status Node
\n
"
);
return
NULL
;
}
psm
=
xmlnode_get_data
(
psmNode
);
return
psm
;
}
static
char
*
create_media_string
(
PurplePresence
*
presence
)
{
const
char
*
title
,
*
game
,
*
office
;
char
*
ret
;
PurpleStatus
*
status
=
purple_presence_get_status
(
presence
,
"tune"
);
if
(
!
status
||
!
purple_status_is_active
(
status
))
return
NULL
;
title
=
purple_status_get_attr_string
(
status
,
PURPLE_TUNE_TITLE
);
game
=
purple_status_get_attr_string
(
status
,
"game"
);
office
=
purple_status_get_attr_string
(
status
,
"office"
);
if
(
title
&&
*
title
)
{
const
char
*
artist
=
purple_status_get_attr_string
(
status
,
PURPLE_TUNE_ARTIST
);
const
char
*
album
=
purple_status_get_attr_string
(
status
,
PURPLE_TUNE_ALBUM
);
ret
=
g_strdup_printf
(
"WMP
\\
0Music
\\
01
\\
0{0}%s%s
\\
0%s
\\
0%s
\\
0%s
\\
0"
,
artist
?
" - {1}"
:
""
,
album
?
" ({2})"
:
""
,
title
,
artist
?
artist
:
""
,
album
?
album
:
""
);
}
else
if
(
game
&&
*
game
)
ret
=
g_strdup_printf
(
"
\\
0Games
\\
01
\\
0Playing {0}
\\
0%s
\\
0"
,
game
);
else
if
(
office
&&
*
office
)
ret
=
g_strdup_printf
(
"
\\
0Office
\\
01
\\
0Editing {0}
\\
0%s
\\
0"
,
office
);
else
ret
=
NULL
;
return
ret
;
}
/* set the MSN's PSM info,Currently Read from the status Line
* Thanks for Cris Code
*/
static
void
msn_set_psm
(
MsnSession
*
session
)
{
PurpleAccount
*
account
;
PurplePresence
*
presence
;
PurpleStatus
*
status
;
char
*
payload
;
const
char
*
statusline
;
gchar
*
statusline_stripped
,
*
media
=
NULL
;
g_return_if_fail
(
session
!=
NULL
);
g_return_if_fail
(
session
->
notification
!=
NULL
);
account
=
session
->
account
;
/* Get the PSM string from Purple's Status Line */
presence
=
purple_account_get_presence
(
account
);
status
=
purple_presence_get_active_status
(
presence
);
statusline
=
purple_status_get_attr_string
(
status
,
"message"
);
/* MSN expects plain text, not HTML */
statusline_stripped
=
purple_markup_strip_html
(
statusline
);
media
=
create_media_string
(
presence
);
g_free
(
session
->
psm
);
session
->
psm
=
msn_build_psm
(
statusline_stripped
,
media
,
session
->
guid
,
session
->
protocol_ver
);
payload
=
session
->
psm
;
msn_notification_send_uux
(
session
,
payload
);
g_free
(
statusline_stripped
);
g_free
(
media
);
}
void
msn_change_status
(
MsnSession
*
session
)
{
PurpleAccount
*
account
;
MsnCmdProc
*
cmdproc
;
MsnTransaction
*
trans
;
MsnUser
*
user
;
MsnObject
*
msnobj
;
const
char
*
state_text
;
GHashTable
*
ui_info
=
purple_core_get_ui_info
();
MsnClientCaps
caps
=
MSN_CLIENT_ID
;
g_return_if_fail
(
session
!=
NULL
);
g_return_if_fail
(
session
->
notification
!=
NULL
);
/* set client caps based on what the UI tells us it is... */
if
(
ui_info
)
{
const
gchar
*
client_type
=
g_hash_table_lookup
(
ui_info
,
"client_type"
);
if
(
client_type
)
{
if
(
strcmp
(
client_type
,
"phone"
)
==
0
||
strcmp
(
client_type
,
"handheld"
)
==
0
)
{
caps
|=
MSN_CAP_VIA_MOBILE
;
}
else
if
(
strcmp
(
client_type
,
"web"
)
==
0
)
{
caps
|=
MSN_CAP_VIA_WEBIM
;
}
else
if
(
strcmp
(
client_type
,
"bot"
)
==
0
)
{
caps
|=
MSN_CAP_BOT
;
}
/* MSN doesn't a "console" type...
What, they have no ncurses UI? :-) */
}
}
account
=
session
->
account
;
cmdproc
=
session
->
notification
->
cmdproc
;
user
=
session
->
user
;
state_text
=
msn_state_get_text
(
msn_state_from_account
(
account
));
/* If we're not logged in yet, don't send the status to the server,
* it will be sent when login completes
*/
if
(
!
session
->
logged_in
)
return
;
msn_set_psm
(
session
);
msnobj
=
msn_user_get_object
(
user
);
if
(
msnobj
==
NULL
)
{
trans
=
msn_transaction_new
(
cmdproc
,
"CHG"
,
"%s %u:%02u 0"
,
state_text
,
caps
,
MSN_CLIENT_ID_EXT_CAPS
);
}
else
{
char
*
msnobj_str
;
msnobj_str
=
msn_object_to_string
(
msnobj
);
trans
=
msn_transaction_new
(
cmdproc
,
"CHG"
,
"%s %u:%02u %s"
,
state_text
,
caps
,
MSN_CLIENT_ID_EXT_CAPS
,
purple_url_encode
(
msnobj_str
));
g_free
(
msnobj_str
);
}
msn_cmdproc_send_trans
(
cmdproc
,
trans
);
}
const
char
*
msn_away_get_text
(
MsnAwayType
type
)
{
g_return_val_if_fail
(
type
<=
MSN_HIDDEN
,
NULL
);
return
_
(
away_text
[
type
]);
}
const
char
*
msn_state_get_text
(
MsnAwayType
state
)
{
static
char
*
status_text
[]
=
{
"NLN"
,
"NLN"
,
"BSY"
,
"IDL"
,
"BRB"
,
"AWY"
,
"PHN"
,
"LUN"
,
"HDN"
,
"HDN"
};
return
status_text
[
state
];
}
MsnAwayType
msn_state_from_account
(
PurpleAccount
*
account
)
{
MsnAwayType
msnstatus
;
PurplePresence
*
presence
;
PurpleStatus
*
status
;
const
char
*
status_id
;
presence
=
purple_account_get_presence
(
account
);
status
=
purple_presence_get_active_status
(
presence
);
status_id
=
purple_status_get_id
(
status
);
if
(
!
strcmp
(
status_id
,
"away"
))
msnstatus
=
MSN_AWAY
;
else
if
(
!
strcmp
(
status_id
,
"brb"
))
msnstatus
=
MSN_BRB
;
else
if
(
!
strcmp
(
status_id
,
"busy"
))
msnstatus
=
MSN_BUSY
;
else
if
(
!
strcmp
(
status_id
,
"phone"
))
msnstatus
=
MSN_PHONE
;
else
if
(
!
strcmp
(
status_id
,
"lunch"
))
msnstatus
=
MSN_LUNCH
;
else
if
(
!
strcmp
(
status_id
,
"invisible"
))
msnstatus
=
MSN_HIDDEN
;
else
msnstatus
=
MSN_ONLINE
;
if
((
msnstatus
==
MSN_ONLINE
)
&&
purple_presence_is_idle
(
presence
))
msnstatus
=
MSN_IDLE
;
return
msnstatus
;
}