pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
gio should be included here
use-gresolver
2015-12-18, Gary Kramlich
1c036daee5b4
gio should be included here
/**
* @file ft.c MSN File Transfer functions
*
* 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
"msnutils.h"
#include
"sbconn.h"
#include
"ft.h"
/**************************************************************************
* Xfer
**************************************************************************/
void
msn_xfer_init
(
PurpleXfer
*
xfer
)
{
MsnSlpCall
*
slpcall
;
/* MsnSlpLink *slplink; */
char
*
content
;
purple_debug_info
(
"msn"
,
"xfer_init
\n
"
);
slpcall
=
purple_xfer_get_protocol_data
(
xfer
);
/* Send Ok */
content
=
g_strdup_printf
(
"SessionID: %lu
\r\n\r\n
"
,
slpcall
->
session_id
);
msn_slp_send_ok
(
slpcall
,
slpcall
->
branch
,
"application/x-msnmsgr-sessionreqbody"
,
content
);
g_free
(
content
);
msn_slplink_send_queued_slpmsgs
(
slpcall
->
slplink
);
}
void
msn_xfer_cancel
(
PurpleXfer
*
xfer
)
{
MsnSlpCall
*
slpcall
;
char
*
content
;
g_return_if_fail
(
xfer
!=
NULL
);
slpcall
=
purple_xfer_get_protocol_data
(
xfer
);
g_return_if_fail
(
slpcall
!=
NULL
);
if
(
purple_xfer_get_status
(
xfer
)
==
PURPLE_XFER_STATUS_CANCEL_LOCAL
)
{
if
(
slpcall
->
started
)
{
msn_slpcall_close
(
slpcall
);
}
else
{
content
=
g_strdup_printf
(
"SessionID: %lu
\r\n\r\n
"
,
slpcall
->
session_id
);
msn_slp_send_decline
(
slpcall
,
slpcall
->
branch
,
"application/x-msnmsgr-sessionreqbody"
,
content
);
g_free
(
content
);
msn_slplink_send_queued_slpmsgs
(
slpcall
->
slplink
);
if
(
purple_xfer_get_xfer_type
(
xfer
)
==
PURPLE_XFER_TYPE_SEND
)
slpcall
->
wasted
=
TRUE
;
else
msn_slpcall_destroy
(
slpcall
);
}
}
}
gssize
msn_xfer_write
(
const
guchar
*
data
,
gsize
len
,
PurpleXfer
*
xfer
)
{
MsnSlpCall
*
slpcall
;
g_return_val_if_fail
(
xfer
!=
NULL
,
-1
);
g_return_val_if_fail
(
data
!=
NULL
,
-1
);
g_return_val_if_fail
(
len
>
0
,
-1
);
g_return_val_if_fail
(
purple_xfer_get_xfer_type
(
xfer
)
==
PURPLE_XFER_TYPE_SEND
,
-1
);
slpcall
=
purple_xfer_get_protocol_data
(
xfer
);
/* Not sure I trust it'll be there */
g_return_val_if_fail
(
slpcall
!=
NULL
,
-1
);
g_return_val_if_fail
(
slpcall
->
xfer_msg
!=
NULL
,
-1
);
slpcall
->
u
.
outgoing
.
len
=
len
;
slpcall
->
u
.
outgoing
.
data
=
data
;
msn_slplink_send_msgpart
(
slpcall
->
slplink
,
slpcall
->
xfer_msg
);
return
MIN
(
MSN_SBCONN_MAX_SIZE
,
len
);
}
gssize
msn_xfer_read
(
guchar
**
data
,
gsize
size
,
PurpleXfer
*
xfer
)
{
MsnSlpCall
*
slpcall
;
gsize
len
;
g_return_val_if_fail
(
xfer
!=
NULL
,
-1
);
g_return_val_if_fail
(
data
!=
NULL
,
-1
);
g_return_val_if_fail
(
purple_xfer_get_xfer_type
(
xfer
)
==
PURPLE_XFER_TYPE_RECEIVE
,
-1
);
slpcall
=
purple_xfer_get_protocol_data
(
xfer
);
/* Not sure I trust it'll be there */
g_return_val_if_fail
(
slpcall
!=
NULL
,
-1
);
/* Just pass up the whole GByteArray. We'll make another. */
*
data
=
slpcall
->
u
.
incoming_data
->
data
;
len
=
slpcall
->
u
.
incoming_data
->
len
;
g_byte_array_free
(
slpcall
->
u
.
incoming_data
,
FALSE
);
slpcall
->
u
.
incoming_data
=
g_byte_array_new
();
return
len
;
}
void
msn_xfer_end_cb
(
MsnSlpCall
*
slpcall
,
MsnSession
*
session
)
{
if
((
purple_xfer_get_status
(
slpcall
->
xfer
)
!=
PURPLE_XFER_STATUS_DONE
)
&&
(
purple_xfer_get_status
(
slpcall
->
xfer
)
!=
PURPLE_XFER_STATUS_CANCEL_REMOTE
)
&&
(
purple_xfer_get_status
(
slpcall
->
xfer
)
!=
PURPLE_XFER_STATUS_CANCEL_LOCAL
))
{
purple_xfer_cancel_remote
(
slpcall
->
xfer
);
}
}
void
msn_xfer_completed_cb
(
MsnSlpCall
*
slpcall
,
const
guchar
*
body
,
gsize
size
)
{
PurpleXfer
*
xfer
=
slpcall
->
xfer
;
purple_xfer_set_completed
(
xfer
,
TRUE
);
purple_xfer_end
(
xfer
);
}
gchar
*
msn_file_context_to_wire
(
MsnFileContext
*
context
)
{
gchar
*
ret
,
*
tmp
;
tmp
=
ret
=
g_new
(
gchar
,
MSN_FILE_CONTEXT_SIZE_V2
+
context
->
preview_len
+
1
);
msn_push32le
(
tmp
,
context
->
length
);
msn_push32le
(
tmp
,
context
->
version
);
msn_push64le
(
tmp
,
context
->
file_size
);
msn_push32le
(
tmp
,
context
->
type
);
memcpy
(
tmp
,
context
->
file_name
,
MAX_FILE_NAME_LEN
*
2
);
tmp
+=
MAX_FILE_NAME_LEN
*
2
;
#if 0
memcpy(tmp, context->unknown1, sizeof(context->unknown1));
tmp += sizeof(context->unknown1);
msn_push32le(tmp, context->unknown2);
#else
memset
(
tmp
,
0
,
sizeof
(
gchar
[
30
]));
tmp
+=
sizeof
(
gchar
[
30
]);
msn_push32le
(
tmp
,
0xffffffff
);
#endif
if
(
context
->
preview
)
{
memcpy
(
tmp
,
context
->
preview
,
context
->
preview_len
);
}
tmp
[
context
->
preview_len
]
=
'\0'
;
return
ret
;
}
MsnFileContext
*
msn_file_context_from_wire
(
const
char
*
buf
,
gsize
len
)
{
MsnFileContext
*
context
;
if
(
!
buf
||
len
<
MSN_FILE_CONTEXT_SIZE_V0
)
return
NULL
;
context
=
g_new
(
MsnFileContext
,
1
);
context
->
length
=
msn_pop32le
(
buf
);
context
->
version
=
msn_pop32le
(
buf
);
if
(
context
->
version
==
0
)
{
if
(
context
->
length
!=
MSN_FILE_CONTEXT_SIZE_V0
)
{
g_free
(
context
);
return
NULL
;
}
}
else
if
(
context
->
version
==
2
)
{
/* The length field is broken for this version. No check. */
context
->
length
=
MSN_FILE_CONTEXT_SIZE_V2
;
if
(
len
<
MSN_FILE_CONTEXT_SIZE_V2
)
{
g_free
(
context
);
return
NULL
;
}
}
else
if
(
context
->
version
==
3
)
{
if
(
context
->
length
!=
MSN_FILE_CONTEXT_SIZE_V3
)
{
g_free
(
context
);
return
NULL
;
}
else
if
(
len
<
MSN_FILE_CONTEXT_SIZE_V3
)
{
g_free
(
context
);
return
NULL
;
}
}
else
{
purple_debug_warning
(
"msn"
,
"Received MsnFileContext with unknown version: %d
\n
"
,
context
->
version
);
g_free
(
context
);
return
NULL
;
}
context
->
file_size
=
msn_pop64le
(
buf
);
context
->
type
=
msn_pop32le
(
buf
);
memcpy
(
context
->
file_name
,
buf
,
MAX_FILE_NAME_LEN
*
2
);
buf
+=
MAX_FILE_NAME_LEN
*
2
;
if
(
context
->
version
>
0
)
{
#if 0
memcpy(context->unknown1, buf, sizeof(context->unknown1));
buf += sizeof(context->unknown1);
context->unknown2 = msn_pop32le(buf);
#else
buf
+=
sizeof
(
gchar
[
30
])
+
sizeof
(
guint32
);
#endif
}
if
(
context
->
type
==
0
&&
len
>
context
->
length
)
{
context
->
preview_len
=
len
-
context
->
length
;
context
->
preview
=
g_memdup
(
buf
,
context
->
preview_len
);
}
else
{
context
->
preview_len
=
0
;
context
->
preview
=
NULL
;
}
return
context
;
}