Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
0db6249a
Commit
0db6249a
authored
Oct 06, 2017
by
Sylvain Berfini
🎩
Browse files
Simple ChatMessageMultipartModifier created + fixed a few things related to ChatMessages
parent
5dc6b956
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
171 additions
and
26 deletions
+171
-26
src/chat/chat-message-p.h
src/chat/chat-message-p.h
+1
-1
src/chat/chat-message.cpp
src/chat/chat-message.cpp
+24
-10
src/chat/chat-room.cpp
src/chat/chat-room.cpp
+1
-1
src/chat/modifier/cpim-chat-message-modifier.cpp
src/chat/modifier/cpim-chat-message-modifier.cpp
+1
-1
src/chat/modifier/encryption-chat-message-modifier.cpp
src/chat/modifier/encryption-chat-message-modifier.cpp
+1
-1
src/chat/modifier/multipart-chat-message-modifier.cpp
src/chat/modifier/multipart-chat-message-modifier.cpp
+79
-5
src/content/content-type.cpp
src/content/content-type.cpp
+43
-5
src/content/content-type.h
src/content/content-type.h
+4
-0
tester/cpim-tester.cpp
tester/cpim-tester.cpp
+17
-2
No files found.
src/chat/chat-message-p.h
View file @
0db6249a
...
...
@@ -152,7 +152,7 @@ private:
bool
isFileTransferInProgressAndValid
();
int
startHttpTransfer
(
std
::
string
url
,
std
::
string
action
,
belle_http_request_listener_callbacks_t
*
cbs
);
void
releaseHttpRequest
();
void
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
();
void
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
(
std
::
string
body
);
L_DECLARE_PUBLIC
(
ChatMessage
);
};
...
...
src/chat/chat-message.cpp
View file @
0db6249a
...
...
@@ -888,12 +888,12 @@ void ChatMessagePrivate::releaseHttpRequest() {
}
}
void
ChatMessagePrivate
::
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
()
{
void
ChatMessagePrivate
::
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
(
string
body
)
{
xmlChar
*
file_url
=
NULL
;
xmlDocPtr
xmlMessageBody
;
xmlNodePtr
cur
;
/* parse the msg body to get all informations from it */
xmlMessageBody
=
xmlParseDoc
((
const
xmlChar
*
)
getText
()
.
c_str
());
xmlMessageBody
=
xmlParseDoc
((
const
xmlChar
*
)
body
.
c_str
());
LinphoneContent
*
content
=
linphone_content_new
();
setFileTransferInformation
(
content
);
...
...
@@ -1005,9 +1005,21 @@ LinphoneReason ChatMessagePrivate::receive() {
// End of message modification
// ---------------------------------------
if
((
errorCode
<=
0
)
&&
(
linphone_core_is_content_type_supported
(
chatRoom
->
getCore
(),
getContentType
().
asString
().
c_str
())
==
FALSE
))
{
errorCode
=
415
;
lError
()
<<
"Unsupported MESSAGE (content-type "
<<
getContentType
().
asString
()
<<
" not recognized)"
;
if
(
errorCode
<=
0
)
{
bool
foundSupportContentType
=
false
;
for
(
auto
it
=
contents
.
begin
();
it
!=
contents
.
end
();
it
++
)
{
if
(
linphone_core_is_content_type_supported
(
chatRoom
->
getCore
(),
it
->
getContentType
().
asString
().
c_str
()))
{
foundSupportContentType
=
true
;
break
;
}
else
{
lError
()
<<
"Unsupported content-type: "
<<
it
->
getContentType
().
asString
();
}
}
if
(
!
foundSupportContentType
)
{
errorCode
=
415
;
lError
()
<<
"No content-type in the contents list is supported..."
;
}
}
if
(
errorCode
>
0
)
{
...
...
@@ -1016,11 +1028,13 @@ LinphoneReason ChatMessagePrivate::receive() {
return
reason
;
}
if
(
getContentType
()
==
ContentType
::
FileTransfer
)
{
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
();
store
=
true
;
}
else
if
(
getContentType
()
==
ContentType
::
PlainText
)
{
store
=
true
;
for
(
auto
it
=
contents
.
begin
();
it
!=
contents
.
end
();
it
++
)
{
if
(
it
->
getContentType
()
==
ContentType
::
FileTransfer
)
{
store
=
true
;
createFileTransferInformationsFromVndGsmaRcsFtHttpXml
(
it
->
getBodyAsString
());
}
else
if
(
it
->
getContentType
()
==
ContentType
::
PlainText
)
{
store
=
true
;
}
}
if
(
store
)
{
...
...
src/chat/chat-room.cpp
View file @
0db6249a
...
...
@@ -402,7 +402,7 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
Content
content
;
content
.
setContentType
(
salMsg
->
content_type
);
content
.
setBody
(
salMsg
->
text
?
salMsg
->
text
:
""
);
msg
->
add
Content
(
content
);
msg
->
setInternal
Content
(
content
);
msg
->
setToAddress
(
op
->
get_to
()
?
op
->
get_to
()
:
linphone_core_get_identity
(
core
));
msg
->
setFromAddress
(
peerAddress
);
...
...
src/chat/modifier/cpim-chat-message-modifier.cpp
View file @
0db6249a
...
...
@@ -24,7 +24,7 @@
#include "content/content.h"
#include "address/address.h"
#include "logger/logger.h"
#include "chat/chat-message
-p
.h"
#include "chat/chat-message.h"
// =============================================================================
...
...
src/chat/modifier/encryption-chat-message-modifier.cpp
View file @
0db6249a
...
...
@@ -26,7 +26,7 @@
#include "content/content.h"
#include "address/address.h"
#include "chat/chat-room.h"
#include "chat/chat-message
-p
.h"
#include "chat/chat-message.h"
// =============================================================================
...
...
src/chat/modifier/multipart-chat-message-modifier.cpp
View file @
0db6249a
...
...
@@ -18,8 +18,11 @@
*/
#include "multipart-chat-message-modifier.h"
#include "address/address.h"
#include "chat/chat-message-p.h"
#include "chat/chat-room.h"
#include "chat/chat-message.h"
#include "logger/logger.h"
// =============================================================================
...
...
@@ -29,15 +32,86 @@ LINPHONE_BEGIN_NAMESPACE
ChatMessageModifier
::
Result
MultipartChatMessageModifier
::
encode
(
shared_ptr
<
ChatMessage
>
message
,
int
*
errorCode
)
{
if
(
message
->
getContents
().
size
()
>
1
)
{
//TODO
LinphoneCore
*
lc
=
message
->
getChatRoom
()
->
getCore
();
char
tmp
[
64
];
lc
->
sal
->
create_uuid
(
tmp
,
sizeof
(
tmp
));
string
boundary
=
tmp
;
stringstream
multipartMessage
;
multipartMessage
<<
"--"
<<
boundary
;
for
(
auto
it
=
message
->
getContents
().
begin
();
it
!=
message
->
getContents
().
end
();
it
++
)
{
multipartMessage
<<
"
\r\n
"
;
multipartMessage
<<
"Content-Type: "
<<
it
->
getContentType
().
asString
()
<<
"
\r\n\r\n
"
;
multipartMessage
<<
it
->
getBodyAsString
()
<<
"
\r\n\r\n
"
;
multipartMessage
<<
"--"
<<
boundary
;
}
multipartMessage
<<
"--"
;
Content
newContent
;
ContentType
newContentType
(
"multipart/mixed"
);
newContentType
.
setParameter
(
"boundary="
+
boundary
);
newContent
.
setContentType
(
newContentType
);
newContent
.
setBody
(
multipartMessage
.
str
());
message
->
setInternalContent
(
newContent
);
return
ChatMessageModifier
::
Result
::
Done
;
}
return
ChatMessageModifier
::
Result
::
Skipped
;
}
}
ChatMessageModifier
::
Result
MultipartChatMessageModifier
::
decode
(
shared_ptr
<
ChatMessage
>
message
,
int
*
errorCode
)
{
//TODO
if
(
false
)
{
// Multipart required
if
(
message
->
getInternalContent
().
getContentType
().
getType
()
==
"multipart"
)
{
string
boundary
=
message
->
getInternalContent
().
getContentType
().
getParameter
();
if
(
boundary
.
empty
())
{
lError
()
<<
"Boundary parameter of content-type not found !"
;
return
ChatMessageModifier
::
Result
::
Error
;
}
size_t
pos
=
boundary
.
find
(
"="
);
if
(
pos
==
string
::
npos
)
{
lError
()
<<
"Parameter seems invalid: "
<<
boundary
;
return
ChatMessageModifier
::
Result
::
Error
;
}
boundary
=
"--"
+
boundary
.
substr
(
pos
+
1
);
lInfo
()
<<
"Multipart boundary is "
<<
boundary
;
const
vector
<
char
>
body
=
message
->
getInternalContent
().
getBody
();
string
contentsString
(
body
.
begin
(),
body
.
end
());
pos
=
contentsString
.
find
(
boundary
);
if
(
pos
==
string
::
npos
)
{
lError
()
<<
"Boundary not found in body !"
;
return
ChatMessageModifier
::
Result
::
Error
;
}
size_t
start
=
pos
+
boundary
.
length
()
+
2
;
// 2 is the size of \r\n
size_t
end
;
do
{
end
=
contentsString
.
find
(
boundary
,
start
);
if
(
end
!=
string
::
npos
)
{
string
contentString
=
contentsString
.
substr
(
start
,
end
-
start
);
size_t
contentTypePos
=
contentString
.
find
(
": "
)
+
2
;
// 2 is the size of :
size_t
endOfLinePos
=
contentString
.
find
(
"
\r\n
"
);
if
(
contentTypePos
>=
endOfLinePos
)
{
lError
()
<<
"Content should start by a 'Content-Type: ' line !"
;
continue
;
}
string
contentTypeString
=
contentString
.
substr
(
contentTypePos
,
endOfLinePos
-
contentTypePos
);
ContentType
contentType
(
contentTypeString
);
endOfLinePos
+=
4
;
// 4 is two time the size of \r\n
string
contentBody
=
contentString
.
substr
(
endOfLinePos
,
contentString
.
length
()
-
(
endOfLinePos
+
4
));
// 4 is two time the size of \r\n
Content
content
;
content
.
setContentType
(
contentType
);
content
.
setBody
(
contentBody
);
message
->
addContent
(
content
);
lInfo
()
<<
"Parsed and added content with type "
<<
contentType
.
asString
();
}
start
=
end
+
boundary
.
length
()
+
2
;
// 2 is the size of \r\n
}
while
(
end
!=
string
::
npos
);
return
ChatMessageModifier
::
Result
::
Done
;
}
...
...
src/content/content-type.cpp
View file @
0db6249a
...
...
@@ -20,7 +20,7 @@
#include "linphone/utils/utils.h"
#include "object/clonable-object-p.h"
#include "logger/logger.h"
#include "content-type.h"
// =============================================================================
...
...
@@ -33,6 +33,7 @@ class ContentTypePrivate : public ClonableObjectPrivate {
public:
string
type
;
string
subType
;
string
parameter
;
};
// -----------------------------------------------------------------------------
...
...
@@ -52,13 +53,22 @@ ContentType::ContentType (const string &contentType) : ClonableObject(*new Conte
L_D
();
size_t
pos
=
contentType
.
find
(
'/'
);
size_t
posParam
=
contentType
.
find
(
"; "
);
size_t
end
=
contentType
.
length
();
if
(
pos
==
string
::
npos
)
return
;
if
(
setType
(
contentType
.
substr
(
0
,
pos
)))
{
if
(
!
setSubType
(
contentType
.
substr
(
pos
+
1
)))
if
(
posParam
!=
string
::
npos
)
{
end
=
posParam
;
}
if
(
!
setSubType
(
contentType
.
substr
(
pos
+
1
,
end
-
(
pos
+
1
))))
d
->
type
.
clear
();
}
if
(
posParam
!=
string
::
npos
)
{
setParameter
(
contentType
.
substr
(
posParam
+
2
));
// We remove the blankspace after the ;
}
}
ContentType
::
ContentType
(
const
string
&
type
,
const
string
&
subType
)
:
ClonableObject
(
*
new
ContentTypePrivate
)
{
...
...
@@ -70,19 +80,30 @@ ContentType::ContentType (const string &type, const string &subType) : ClonableO
}
}
ContentType
::
ContentType
(
const
ContentType
&
src
)
:
ContentType
(
src
.
getType
(),
src
.
getSubType
())
{}
ContentType
::
ContentType
(
const
string
&
type
,
const
string
&
subType
,
const
string
&
parameter
)
:
ClonableObject
(
*
new
ContentTypePrivate
)
{
L_D
();
if
(
setType
(
type
))
{
if
(
!
setSubType
(
subType
))
d
->
type
.
clear
();
}
setParameter
(
parameter
);
}
ContentType
::
ContentType
(
const
ContentType
&
src
)
:
ContentType
(
src
.
getType
(),
src
.
getSubType
(),
src
.
getParameter
())
{}
ContentType
&
ContentType
::
operator
=
(
const
ContentType
&
src
)
{
if
(
this
!=
&
src
)
{
setType
(
src
.
getType
());
setSubType
(
src
.
getSubType
());
setParameter
(
src
.
getParameter
());
}
return
*
this
;
}
bool
ContentType
::
operator
==
(
const
ContentType
&
contentType
)
const
{
return
getType
()
==
contentType
.
getType
()
&&
getSubType
()
==
contentType
.
getSubType
();
return
getType
()
==
contentType
.
getType
()
&&
getSubType
()
==
contentType
.
getSubType
()
&&
getParameter
()
==
contentType
.
getParameter
()
;
}
bool
ContentType
::
operator
!=
(
const
ContentType
&
contentType
)
const
{
...
...
@@ -117,6 +138,16 @@ bool ContentType::setSubType (const string &subType) {
return
false
;
}
const
string
&
ContentType
::
getParameter
()
const
{
L_D
();
return
d
->
parameter
;
}
void
ContentType
::
setParameter
(
const
string
&
parameter
)
{
L_D
();
d
->
parameter
=
parameter
;
}
bool
ContentType
::
isValid
()
const
{
L_D
();
return
!
d
->
type
.
empty
()
&&
!
d
->
subType
.
empty
();
...
...
@@ -124,7 +155,14 @@ bool ContentType::isValid () const {
string
ContentType
::
asString
()
const
{
L_D
();
return
isValid
()
?
d
->
type
+
"/"
+
d
->
subType
:
""
;
if
(
isValid
())
{
string
asString
=
d
->
type
+
"/"
+
d
->
subType
;
if
(
!
d
->
parameter
.
empty
())
{
asString
+=
"; "
+
d
->
parameter
;
}
return
asString
;
}
return
""
;
}
LINPHONE_END_NAMESPACE
src/content/content-type.h
View file @
0db6249a
...
...
@@ -32,6 +32,7 @@ class LINPHONE_PUBLIC ContentType : public ClonableObject {
public:
ContentType
(
const
std
::
string
&
contentType
=
""
);
ContentType
(
const
std
::
string
&
type
,
const
std
::
string
&
subType
);
ContentType
(
const
std
::
string
&
type
,
const
std
::
string
&
subType
,
const
std
::
string
&
parameter
);
ContentType
(
const
ContentType
&
src
);
ContentType
&
operator
=
(
const
ContentType
&
src
);
...
...
@@ -52,6 +53,9 @@ public:
const
std
::
string
&
getSubType
()
const
;
bool
setSubType
(
const
std
::
string
&
subType
);
const
std
::
string
&
getParameter
()
const
;
void
setParameter
(
const
std
::
string
&
parameter
);
std
::
string
asString
()
const
;
static
const
ContentType
Cpim
;
...
...
tester/cpim-tester.cpp
View file @
0db6249a
...
...
@@ -382,7 +382,7 @@ static void build_message () {
BC_ASSERT_STRING_EQUAL
(
strMessage
.
c_str
(),
expectedMessage
.
c_str
());
}
static
void
cpim_chat_message_modifier
(
void
)
{
static
void
cpim_chat_message_modifier
_base
(
bool_t
use_multipart
)
{
LinphoneCoreManager
*
marie
=
linphone_core_manager_new
(
"marie_rc"
);
LinphoneCoreManager
*
pauline
=
linphone_core_manager_new
(
"pauline_tcp_rc"
);
LpConfig
*
config
=
linphone_core_get_config
(
marie
->
lc
);
...
...
@@ -392,6 +392,12 @@ static void cpim_chat_message_modifier(void) {
shared_ptr
<
ChatRoom
>
marieRoom
=
ObjectFactory
::
create
<
BasicChatRoom
>
(
marie
->
lc
,
paulineAddress
);
shared_ptr
<
ChatMessage
>
marieMessage
=
marieRoom
->
createMessage
(
"Hello CPIM"
);
if
(
use_multipart
)
{
Content
content
;
content
.
setContentType
(
ContentType
::
PlainText
);
content
.
setBody
(
"Hello Part 2"
);
marieMessage
->
addContent
(
content
);
}
marieRoom
->
sendMessage
(
marieMessage
);
BC_ASSERT_TRUE
(
wait_for
(
pauline
->
lc
,
marie
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneMessageReceived
,
1
));
...
...
@@ -407,6 +413,14 @@ static void cpim_chat_message_modifier(void) {
linphone_core_manager_destroy
(
pauline
);
}
static
void
cpim_chat_message_modifier
(
void
)
{
cpim_chat_message_modifier_base
(
FALSE
);
}
static
void
cpim_chat_message_modifier_with_multipart_body
(
void
)
{
cpim_chat_message_modifier_base
(
TRUE
);
}
test_t
cpim_tests
[]
=
{
TEST_NO_TAG
(
"Parse minimal CPIM message"
,
parse_minimal_message
),
TEST_NO_TAG
(
"Set generic header name"
,
set_generic_header_name
),
...
...
@@ -417,7 +431,8 @@ test_t cpim_tests[] = {
TEST_NO_TAG
(
"Parse RFC example"
,
parse_rfc_example
),
TEST_NO_TAG
(
"Parse Message with generic header parameters"
,
parse_message_with_generic_header_parameters
),
TEST_NO_TAG
(
"Build Message"
,
build_message
),
TEST_NO_TAG
(
"CPIM chat message modifier"
,
cpim_chat_message_modifier
)
TEST_NO_TAG
(
"CPIM chat message modifier"
,
cpim_chat_message_modifier
),
TEST_NO_TAG
(
"CPIM chat message modifier with multipart body"
,
cpim_chat_message_modifier_with_multipart_body
),
};
test_suite_t
cpim_test_suite
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment