summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2012-04-26 20:02:14 +0000
committerwatcherhd <watcherhd@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb>2012-04-26 20:02:14 +0000
commit2ec2fe72f5754f59363335f9d5578600022661a1 (patch)
tree19fceb0fb54dbb8247dca7c7c094699e330882e3
parent0dec0977c6ca0bfaacb059d1a43093b0a14be3e4 (diff)
FacebookRM: version bump
Version 0.0.8.1 ! Fixed getting notifications on login ! Fixed getting unread messages on login ! Getting unread messages on login with right timestamp ! Fixed getting newsfeeds ! Fixed related to deleting contacts from miranda/server + New newsfeed type option "Applications and Games" + Contacts now have MirVer "Facebook" (for Fingerpring plugin) + Getting attachements for unread messages on login ! Fixed avatars in Miranda 0.10.0#3 and newer (thanks borkra) ! Some small fixes (thanks borkra) x Doesn't work notification about friend requests git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@289 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb
-rw-r--r--FacebookRM/avatars.cpp14
-rw-r--r--FacebookRM/build.h2
-rw-r--r--FacebookRM/client.h12
-rw-r--r--FacebookRM/common.h4
-rw-r--r--FacebookRM/communication.cpp154
-rw-r--r--FacebookRM/connection.cpp11
-rw-r--r--FacebookRM/constants.h19
-rw-r--r--FacebookRM/contacts.cpp76
-rw-r--r--FacebookRM/db.h1
-rw-r--r--FacebookRM/entities.h3
-rw-r--r--FacebookRM/events.cpp15
-rw-r--r--FacebookRM/facebook.rc4
-rw-r--r--FacebookRM/facebook_10.vcxproj.filters12
-rw-r--r--FacebookRM/json.cpp98
-rw-r--r--FacebookRM/json.h1
-rw-r--r--FacebookRM/messages.cpp9
-rw-r--r--FacebookRM/process.cpp209
-rw-r--r--FacebookRM/proto.cpp16
-rw-r--r--FacebookRM/proto.h4
-rw-r--r--FacebookRM/utils.cpp11
-rw-r--r--FacebookRM/utils.h7
21 files changed, 298 insertions, 384 deletions
diff --git a/FacebookRM/avatars.cpp b/FacebookRM/avatars.cpp
index c3648ba..bed3f0c 100644
--- a/FacebookRM/avatars.cpp
+++ b/FacebookRM/avatars.cpp
@@ -180,8 +180,14 @@ int FacebookProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
if (GetDbAvatarInfo(*AI, NULL))
{
- if (_access(AI->filename, 0) || (wParam & GAIF_FORCE))
- {
+ if (!_access(AI->filename, 0))
+ {
+ LOG("***** Giving AvatarInfo: %s", AI->filename);
+ return GAIR_SUCCESS;
+ }
+
+ if (wParam & GAIF_FORCE)
+ {
LOG("***** Starting avatar request thread for %s", AI->filename);
ScopedLock s( avatar_lock_ );
@@ -192,12 +198,8 @@ int FacebookProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
if (is_empty)
ForkThread(&FacebookProto::UpdateAvatarWorker, this, NULL);
}
-
return GAIR_WAITFOR;
}
-
- LOG("***** Giving AvatarInfo: %s", AI->filename);
- return GAIR_SUCCESS;
}
return GAIR_NOAVATAR;
}
diff --git a/FacebookRM/build.h b/FacebookRM/build.h
index bcbabbb..eb53310 100644
--- a/FacebookRM/build.h
+++ b/FacebookRM/build.h
@@ -1 +1 @@
-#define __BUILD 2119
+#define __BUILD 2122
diff --git a/FacebookRM/client.h b/FacebookRM/client.h
index 45f4bb3..40555c2 100644
--- a/FacebookRM/client.h
+++ b/FacebookRM/client.h
@@ -41,7 +41,7 @@ public:
msgid_ = error_count_ = last_feeds_update_ = last_notification_time_ = 0;
- is_idle_ = invisible_ = is_typing_ = false;
+ https_ = is_idle_ = invisible_ = is_typing_ = false;
buddies_lock_ = send_message_lock_ = NULL;
hMsgCon = NULL;
@@ -75,6 +75,7 @@ public:
bool invisible_;
bool is_typing_;
bool is_idle_;
+ bool https_;
time_t last_feeds_update_;
unsigned __int64 last_notification_time_;
int msgid_;
@@ -141,7 +142,6 @@ public:
HANDLE send_message_lock_;
bool buddy_list( );
- bool facepiles( );
bool load_friends( );
bool feeds( );
@@ -164,15 +164,15 @@ public:
// HTTP communication
- http::response flap( const int request_type, std::string* request_data = NULL );
+ http::response flap( const int request_type, std::string* request_data = NULL, std::string* request_get_data = NULL );
bool save_url(const std::string &url,const std::string &filename, HANDLE &nlc);
DWORD choose_security_level( int );
int choose_method( int );
std::string choose_proto( int );
- std::string choose_server( int, std::string* data = NULL );
- std::string choose_action( int, std::string* data = NULL );
- std::string choose_request_url( int, std::string* data = NULL );
+ std::string choose_server( int, std::string* data = NULL, std::string* get_data = NULL );
+ std::string choose_action( int, std::string* data = NULL, std::string* get_data = NULL );
+ std::string choose_request_url( int, std::string* data = NULL, std::string* get_data = NULL );
NETLIBHTTPHEADER* get_request_headers( int request_type, int* headers_count );
diff --git a/FacebookRM/common.h b/FacebookRM/common.h
index 4fed93e..b1f2d2c 100644
--- a/FacebookRM/common.h
+++ b/FacebookRM/common.h
@@ -81,8 +81,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_utils.h>
#include <m_hotkeys.h>
-#include "m_updater.h"
-#include "m_folders.h"
+#include <m_updater.h>
+#include <m_folders.h>
class FacebookProto;
diff --git a/FacebookRM/communication.cpp b/FacebookRM/communication.cpp
index a7230fc..d17e40e 100644
--- a/FacebookRM/communication.cpp
+++ b/FacebookRM/communication.cpp
@@ -27,13 +27,13 @@ void facebook_client::client_notify( TCHAR* message )
parent->NotifyEvent( parent->m_tszUserName, message, NULL, FACEBOOK_EVENT_CLIENT );
}
-http::response facebook_client::flap( const int request_type, std::string* request_data )
+http::response facebook_client::flap( const int request_type, std::string* request_data, std::string* request_get_data )
{
NETLIBHTTPREQUEST nlhr = {sizeof( NETLIBHTTPREQUEST )};
nlhr.requestType = choose_method( request_type );
- std::string url = choose_request_url( request_type, request_data );
+ std::string url = choose_request_url( request_type, request_data, request_get_data );
nlhr.szUrl = (char*)url.c_str( );
- nlhr.flags = NLHRF_HTTP11 | /*NLHRF_NODUMP |*/ choose_security_level( request_type );
+ nlhr.flags = NLHRF_HTTP11 | NLHRF_NODUMP | choose_security_level( request_type );
nlhr.headers = get_request_headers( request_type, &nlhr.headersCount );
switch (request_type)
@@ -57,7 +57,6 @@ http::response facebook_client::flap( const int request_type, std::string* reque
switch ( request_type )
{
case FACEBOOK_REQUEST_LOGIN:
- case FACEBOOK_REQUEST_SETUP_MACHINE:
nlhr.nlc = NULL;
break;
@@ -111,6 +110,9 @@ http::response facebook_client::flap( const int request_type, std::string* reque
// is compaired in all communication requests
}
+ if (DBGetContactSettingByte( NULL, parent->m_szModuleName, FACEBOOK_KEY_VALIDATE_RESPONSE, 0 ) == 1)
+ validate_response(&resp);
+
return resp;
}
@@ -122,7 +124,13 @@ bool facebook_client::validate_response( http::response* resp )
return false;
}
-/* std::string cookie = utils::text::source_get_value(&resp->data, 2, "setCookie(\\\"", ");");
+ if (DBGetContactSettingByte( NULL, parent->m_szModuleName, FACEBOOK_KEY_VALIDATE_RESPONSE, 0 ) == 2) {
+ return true;
+ }
+
+/*
+ // TODO: Is this from jarvis? Or me? Add it?
+ std::string cookie = utils::text::source_get_value(&resp->data, 2, "setCookie(\\\"", ");");
if (!cookie.empty()) {
std::string cookie_name = utils::text::source_get_value(&cookie, 1, "\\\"");
std::string cookie_value = utils::text::source_get_value(&cookie, 3, "\\\"", "\\\"", "\\\"");
@@ -204,9 +212,10 @@ bool facebook_client::handle_error( std::string method, bool force_disconnect )
DWORD facebook_client::choose_security_level( int request_type )
{
- if ( DBGetContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS ) ) {
+ if (this->https_)
+ {
if ( request_type != FACEBOOK_REQUEST_MESSAGES_RECEIVE
- || DBGetContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL, DEFAULT_FORCE_HTTPS_CHANNEL ) )
+ || DBGetContactSettingByte( NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL, DEFAULT_FORCE_HTTPS_CHANNEL ) )
return NLHRF_SSL;
}
@@ -219,7 +228,6 @@ DWORD facebook_client::choose_security_level( int request_type )
// case FACEBOOK_REQUEST_LOGOUT:
// case FACEBOOK_REQUEST_HOME:
// case FACEBOOK_REQUEST_BUDDY_LIST:
-// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
// case FACEBOOK_REQUEST_ADD_FRIEND:
@@ -232,7 +240,6 @@ DWORD facebook_client::choose_security_level( int request_type )
// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
-// case FACEBOOK_REQUEST_ASYNC_GET:
// case FACEBOOK_REQUEST_TYPING_SEND:
default:
return ( DWORD )0;
@@ -246,7 +253,6 @@ int facebook_client::choose_method( int request_type )
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
- case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
case FACEBOOK_REQUEST_VISIBILITY:
@@ -264,7 +270,6 @@ int facebook_client::choose_method( int request_type )
// case FACEBOOK_REQUEST_NOTIFICATIONS:
// case FACEBOOK_REQUEST_RECONNECT:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
-// case FACEBOOK_REQUEST_ASYNC_GET:
default:
return REQUEST_GET;
}
@@ -272,9 +277,9 @@ int facebook_client::choose_method( int request_type )
std::string facebook_client::choose_proto( int request_type )
{
- if ( DBGetContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS ) ) {
+ if (this->https_) {
if ( request_type != FACEBOOK_REQUEST_MESSAGES_RECEIVE
- || DBGetContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL, DEFAULT_FORCE_HTTPS_CHANNEL ) )
+ || DBGetContactSettingByte( NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS_CHANNEL, DEFAULT_FORCE_HTTPS_CHANNEL ) )
return HTTP_PROTO_SECURE;
}
@@ -286,7 +291,6 @@ std::string facebook_client::choose_proto( int request_type )
// case FACEBOOK_REQUEST_NOTIFICATIONS:
// case FACEBOOK_REQUEST_RECONNECT:
// case FACEBOOK_REQUEST_BUDDY_LIST:
-// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_STATUS_SET:
// case FACEBOOK_REQUEST_MESSAGE_SEND:
@@ -294,7 +298,6 @@ std::string facebook_client::choose_proto( int request_type )
// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
-// case FACEBOOK_REQUEST_ASYNC_GET:
// case FACEBOOK_REQUEST_TYPING_SEND:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
// case FACEBOOK_REQUEST_ADD_FRIEND:
@@ -307,7 +310,7 @@ std::string facebook_client::choose_proto( int request_type )
}
}
-std::string facebook_client::choose_server( int request_type, std::string* data )
+std::string facebook_client::choose_server( int request_type, std::string* data, std::string* get_data )
{
switch ( request_type )
{
@@ -328,7 +331,6 @@ std::string facebook_client::choose_server( int request_type, std::string* data
// case FACEBOOK_REQUEST_LOGOUT:
// case FACEBOOK_REQUEST_HOME:
// case FACEBOOK_REQUEST_BUDDY_LIST:
-// case FACEBOOK_REQUEST_FACEPILES:
// case FACEBOOK_REQUEST_LOAD_FRIENDS:
// case FACEBOOK_REQUEST_FEEDS:
// case FACEBOOK_REQUEST_NOTIFICATIONS:
@@ -338,7 +340,6 @@ std::string facebook_client::choose_server( int request_type, std::string* data
// case FACEBOOK_REQUEST_VISIBILITY:
// case FACEBOOK_REQUEST_TABS:
// case FACEBOOK_REQUEST_ASYNC:
-// case FACEBOOK_REQUEST_ASYNC_GET:
// case FACEBOOK_REQUEST_TYPING_SEND:
// case FACEBOOK_REQUEST_SETUP_MACHINE:
// case FACEBOOK_REQUEST_DELETE_FRIEND:
@@ -348,7 +349,7 @@ std::string facebook_client::choose_server( int request_type, std::string* data
}
}
-std::string facebook_client::choose_action( int request_type, std::string* data )
+std::string facebook_client::choose_action( int request_type, std::string* data, std::string* get_data )
{
switch ( request_type )
{
@@ -367,13 +368,10 @@ std::string facebook_client::choose_action( int request_type, std::string* data
case FACEBOOK_REQUEST_BUDDY_LIST:
return "/ajax/chat/buddy_list.php?__a=1";
- case FACEBOOK_REQUEST_FACEPILES:
- return "/ajax/groups/chat/update_facepiles.php?__a=1";
-
case FACEBOOK_REQUEST_LOAD_FRIENDS:
{
- std::string action = "/ajax/chat/user_info_all.php?__a=1&viewer=%s";
- utils::text::replace_first( &action, "%s", self_.user_id );
+ std::string action = "/ajax/chat/user_info_all.php?__a=1&viewer=%s&__user=%s";
+ utils::text::replace_all( &action, "%s", self_.user_id );
return action;
}
@@ -391,16 +389,17 @@ std::string facebook_client::choose_action( int request_type, std::string* data
{
std::string action = "/ajax/intent.php?filter=";
action += get_newsfeed_type();
- action += "&request_type=1&__a=1&newest=%s&ignore_self=true";
+ action += "&request_type=4&__a=1&newest=%s&ignore_self=true&load_newer=true&__user=%s";
std::string newest = utils::conversion::to_string((void*)&this->last_feeds_update_, UTILS_CONV_TIME_T);
utils::text::replace_first( &action, "%s", newest );
+ utils::text::replace_first( &action, "%s", self_.user_id );
return action;
}
case FACEBOOK_REQUEST_NOTIFICATIONS:
{
- std::string action = "/ajax/notifications/get.php?__a=1&user=%s&time=0&version=2";
- utils::text::replace_first( &action, "%s", self_.user_id );
+ std::string action = "/ajax/notifications/get.php?__a=1&user=%s&time=0&version=2&__user=%s";
+ utils::text::replace_all( &action, "%s", self_.user_id );
return action;
}
@@ -409,7 +408,7 @@ std::string facebook_client::choose_action( int request_type, std::string* data
std::string action = "/ajax/presence/reconnect.php?__a=1&reason=%s&fb_dtsg=%s&post_form_id=%s&__user=%s";
if (this->chat_reconnect_reason_.empty())
- this->chat_reconnect_reason_ = "0"; // 6?
+ this->chat_reconnect_reason_ = "6";
utils::text::replace_first( &action, "%s", this->chat_reconnect_reason_ );
utils::text::replace_first( &action, "%s", this->dtsg_ );
@@ -440,18 +439,17 @@ std::string facebook_client::choose_action( int request_type, std::string* data
}
case FACEBOOK_REQUEST_VISIBILITY:
- return "/ajax/chat/visibility.php?__a=1";
+ return "/ajax/chat/privacy/visibility.php?__a=1";
case FACEBOOK_REQUEST_TABS:
return "/ajax/chat/tabs.php?__a=1";
case FACEBOOK_REQUEST_ASYNC:
- return "/ajax/messaging/async.php?__a=1";
-
- case FACEBOOK_REQUEST_ASYNC_GET:
{
- std::string action = "/ajax/messaging/async.php?__a=1&%s";
- utils::text::replace_first( &action, "%s", (*data) );
+ std::string action = "/ajax/messaging/async.php?__a=1";
+ if (get_data != NULL) {
+ action += "&" + (*get_data);
+ }
return action;
}
@@ -463,11 +461,11 @@ std::string facebook_client::choose_action( int request_type, std::string* data
}
}
-std::string facebook_client::choose_request_url( int request_type, std::string* data )
+std::string facebook_client::choose_request_url( int request_type, std::string* data, std::string* get_data )
{
std::string url = choose_proto( request_type );
- url.append( choose_server( request_type, data ) );
- url.append( choose_action( request_type, data ) );
+ url.append( choose_server( request_type, data, get_data ) );
+ url.append( choose_action( request_type, data, get_data ) );
return url;
}
@@ -478,14 +476,12 @@ NETLIBHTTPHEADER* facebook_client::get_request_headers( int request_type, int* h
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
- case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_LOAD_FRIENDS:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
case FACEBOOK_REQUEST_VISIBILITY:
case FACEBOOK_REQUEST_TABS:
case FACEBOOK_REQUEST_ASYNC:
- case FACEBOOK_REQUEST_ASYNC_GET:
case FACEBOOK_REQUEST_TYPING_SEND:
case FACEBOOK_REQUEST_DELETE_FRIEND:
case FACEBOOK_REQUEST_ADD_FRIEND:
@@ -509,14 +505,12 @@ NETLIBHTTPHEADER* facebook_client::get_request_headers( int request_type, int* h
case FACEBOOK_REQUEST_LOGIN:
case FACEBOOK_REQUEST_SETUP_MACHINE:
case FACEBOOK_REQUEST_BUDDY_LIST:
- case FACEBOOK_REQUEST_FACEPILES:
case FACEBOOK_REQUEST_LOAD_FRIENDS:
case FACEBOOK_REQUEST_STATUS_SET:
case FACEBOOK_REQUEST_MESSAGE_SEND:
case FACEBOOK_REQUEST_VISIBILITY:
case FACEBOOK_REQUEST_TABS:
case FACEBOOK_REQUEST_ASYNC:
- case FACEBOOK_REQUEST_ASYNC_GET:
case FACEBOOK_REQUEST_TYPING_SEND:
case FACEBOOK_REQUEST_DELETE_FRIEND:
case FACEBOOK_REQUEST_ADD_FRIEND:
@@ -661,12 +655,13 @@ bool facebook_client::login(const std::string &username,const std::string &passw
if ( resp.code == HTTP_CODE_FOUND && resp.headers.find("Location") != resp.headers.end() )
{
// Check whether HTTPS connection is required and we don't have enabled it
- if ( !DBGetContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS ) )
+ if (!this->https_)
{
if ( resp.headers["Location"].find("https://") != std::string::npos )
{
client_notify(TranslateT("Your account requires HTTPS connection. Activating."));
- DBWriteContactSettingByte( NULL, parent->m_szProtoName, FACEBOOK_KEY_FORCE_HTTPS, 1 );
+ DBWriteContactSettingByte(NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS, 1);
+ this->https_ = true;
}
}
@@ -819,7 +814,7 @@ bool facebook_client::home( )
this->logout_hash_ = utils::text::source_get_value( &resp.data, 2, "<input type=\"hidden\" autocomplete=\"off\" name=\"h\" value=\"", "\"" );
parent->Log(" Got self logout hash: %s", this->logout_hash_.c_str());
-
+ // TODO: DIrectly get that friend requests
// Get friend requests count and notify it
std::string str_count = utils::text::source_get_value( &resp.data, 2, "<span id=\"requestsCountValue\">", "</span>" );
if ( str_count.length() && str_count != std::string( "0" ) )
@@ -842,8 +837,6 @@ bool facebook_client::home( )
parent->NotifyEvent( parent->m_tszUserName, tmessage, NULL, FACEBOOK_EVENT_OTHER, TEXT(FACEBOOK_URL_MESSAGES) );
mir_free( tmessage );
}
- } else { // Parse messages directly for contacts
- ForkThread( &FacebookProto::ProcessUnreadMessages, this->parent, NULL );
}
str_count = utils::text::source_get_value( &resp.data, 2, "<span id=\"notificationsCountValue\">", "</span>" );
@@ -891,13 +884,14 @@ bool facebook_client::chat_state( bool online )
handle_entry( "chat_state" );
std::string data = "visibility=";
- data += ( online ) ? "true" : "false";
+ data += ( online ) ? "1" : "0";
data += "&window_id=0";
data += "&post_form_id=";
data += ( post_form_id_.length( ) ) ? post_form_id_ : "0";
data += "&post_form_id_source=AsyncRequest";
data += "&fb_dtsg=" + this->dtsg_;
- data += "&lsd=";
+ data += "&lsd=&phstamp=0&__user=";
+ data += self_.user_id;
http::response resp = flap( FACEBOOK_REQUEST_VISIBILITY, &data );
return handle_success( "chat_state" );
@@ -986,51 +980,6 @@ bool facebook_client::buddy_list( )
}
}
-bool facebook_client::facepiles( )
-{
- handle_entry( "facepiles" );
-
- int count = (int)CallServiceSync(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)parent->m_szModuleName);
- for ( int i = 0; i < count; i++ ) {
- GC_INFO gci = {0};
- gci.Flags = BYINDEX | TYPE | ID;
- gci.iItem = i;
- gci.pszModule = parent->m_szModuleName;
- if ( !CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci ) && gci.iType == GCW_CHATROOM ) {
- char *id = mir_t2a(gci.pszID);
-
- // Prepare data
- std::string data = "id=";
- data += id;
- data += "&post_form_id=" + this->post_form_id_ + "&fb_dtsg=" + this->dtsg_ + "&lsd=&post_form_id_source=AsyncRequest&__user=" + this->self_.user_id + "&phstamp=0";
-
- // Get facepiles
- http::response resp = flap( FACEBOOK_REQUEST_FACEPILES, &data );
-
- // Process result data
- validate_response(&resp);
-
- std::string chat_id = id;
- mir_free(id);
-
- switch ( resp.code )
- {
- case HTTP_CODE_OK:
- ForkThread( &FacebookProto::ProcessFacepiles, this->parent, new send_chat(chat_id, resp.data) );
- break;
-
- case HTTP_CODE_FAKE_ERROR:
- case HTTP_CODE_FAKE_DISCONNECTED:
- default:
- return handle_error( "facepiles" );
- }
-
- }
- }
-
- return handle_success( "facepiles" );
-}
-
bool facebook_client::load_friends( )
{
handle_entry( "load_friends" );
@@ -1066,18 +1015,12 @@ bool facebook_client::feeds( )
// Process result data
validate_response(&resp);
- std::string::size_type pos = 0;
switch ( resp.code )
{
case HTTP_CODE_OK:
- pos = resp.data.find( "\"storyCount\":" );
- if ( pos != std::string::npos )
- {
- if (resp.data.substr( pos + 13, 1 ) != "0")
- {
- std::string* response_data = new std::string( resp.data );
- ForkThread( &FacebookProto::ProcessFeeds, this->parent, ( void* )response_data );
- }
+ if (resp.data.find("\"num_stories\":0") == std::string::npos) {
+ std::string* response_data = new std::string( resp.data );
+ ForkThread( &FacebookProto::ProcessFeeds, this->parent, ( void* )response_data );
}
return handle_success( "feeds" );
@@ -1276,6 +1219,8 @@ void facebook_client::close_chat( std::string message_recipient )
data += "&post_form_id_source=AsyncRequest";
data += "&fb_dtsg=";
data += ( this->dtsg_.length( ) ) ? this->dtsg_ : "0";
+ data += "&__user=";
+ data += self_.user_id;
http::response resp = flap( FACEBOOK_REQUEST_TABS, &data );
}
@@ -1290,7 +1235,8 @@ void facebook_client::chat_mark_read( std::string message_recipient )
data += ( post_form_id_.length( ) ) ? post_form_id_ : "0";
data += "&fb_dtsg=";
data += ( this->dtsg_.length( ) ) ? this->dtsg_ : "0";
- data += "&post_form_id_source=AsyncRequest&lsd=";
+ data += "&post_form_id_source=AsyncRequest&lsd=&__user=";
+ data += self_.user_id;
http::response resp = flap( FACEBOOK_REQUEST_ASYNC, &data );
}
@@ -1338,7 +1284,7 @@ bool facebook_client::save_url(const std::string &url,const std::string &filenam
NETLIBHTTPREQUEST *resp;
req.requestType = REQUEST_GET;
req.szUrl = const_cast<char*>(url.c_str());
- req.flags = NLHRF_HTTP11 | NLHRF_REDIRECT | NLHRF_PERSISTENT;
+ req.flags = NLHRF_HTTP11 | NLHRF_REDIRECT | NLHRF_PERSISTENT | NLHRF_NODUMP;
req.nlc = nlc;
resp = reinterpret_cast<NETLIBHTTPREQUEST*>(CallService( MS_NETLIB_HTTPTRANSACTION,
diff --git a/FacebookRM/connection.cpp b/FacebookRM/connection.cpp
index d26b9a3..d60b1ec 100644
--- a/FacebookRM/connection.cpp
+++ b/FacebookRM/connection.cpp
@@ -91,6 +91,9 @@ void FacebookProto::ChangeStatus(void*)
facy.load_friends();
+ if (getByte(FACEBOOK_KEY_PARSE_MESSAGES, DEFAULT_PARSE_MESSAGES))
+ ForkThread( &FacebookProto::ProcessUnreadMessages, this );
+
setDword( "LogonTS", (DWORD)time(NULL) );
ForkThread( &FacebookProto::UpdateLoop, this );
ForkThread( &FacebookProto::MessageLoop, this );
@@ -123,7 +126,6 @@ void FacebookProto::ChangeStatus(void*)
facy.chat_state( m_iDesiredStatus != ID_STATUS_INVISIBLE );
facy.buddy_list( );
- facy.facepiles( );
m_iStatus = facy.self_.status_id = m_iDesiredStatus;
ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
@@ -175,6 +177,9 @@ bool FacebookProto::NegotiateConnection( )
DBFreeVariant(&dbv);
}
+ // Get info about secured connection
+ facy.https_ = DBGetContactSettingByte(NULL, m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS, DEFAULT_FORCE_HTTPS ) != 0;
+
return facy.login( user, pass );
}
@@ -189,9 +194,6 @@ void FacebookProto::UpdateLoop(void *)
if ( !facy.invisible_ )
if ( !facy.buddy_list( ) )
break;
- if ( getByte( FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS) )
- if ( !facy.facepiles( ) )
- break;
}
if ( i == 2 && getByte( FACEBOOK_KEY_EVENT_FEEDS_ENABLE, DEFAULT_EVENT_FEEDS_ENABLE ) )
if ( !facy.feeds( ) )
@@ -202,6 +204,7 @@ void FacebookProto::UpdateLoop(void *)
LOG( "***** FacebookProto::UpdateLoop[%d] waking up...", tim );
}
+ ResetEvent(update_loop_lock_);
LOG( "<<<<< Exiting FacebookProto::UpdateLoop[%d]", tim );
}
diff --git a/FacebookRM/constants.h b/FacebookRM/constants.h
index f02283b..3e0aaac 100644
--- a/FacebookRM/constants.h
+++ b/FacebookRM/constants.h
@@ -23,13 +23,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
// Version management
-#include "build.h"
-#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 8, 0)
-#define __VERSION_STRING "0.0.8.0"
+#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 8, 1)
+#define __VERSION_STRING "0.0.8.1"
// Product management
#define FACEBOOK_NAME "Facebook"
-#define FACEBOOK_URL_HOMEPAGE "http://www.facebook.com/"
+#define FACEBOOK_URL_HOMEPAGE "http://www.facebook.com"
#define FACEBOOK_URL_REQUESTS "http://www.facebook.com/n/?reqs.php"
#define FACEBOOK_URL_MESSAGES "http://www.facebook.com/n/?inbox"
#define FACEBOOK_URL_NOTIFICATIONS "http://www.facebook.com/n/?notifications.php"
@@ -94,7 +93,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FACEBOOK_REQUEST_LOAD_FRIENDS 121 // getting list of all friends
#define FACEBOOK_REQUEST_DELETE_FRIEND 122 // deleting friends
#define FACEBOOK_REQUEST_ADD_FRIEND 123 // adding friends
-#define FACEBOOK_REQUEST_FACEPILES 124 // getting list of contacts in chat
#define FACEBOOK_REQUEST_FEEDS 125 // getting feeds
#define FACEBOOK_REQUEST_NOTIFICATIONS 126 // getting notifications
#define FACEBOOK_REQUEST_RECONNECT 130 // getting __sequence_num__ and __channel_id__
@@ -103,9 +101,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FACEBOOK_REQUEST_MESSAGES_RECEIVE 301 // receiving messages
#define FACEBOOK_REQUEST_TYPING_SEND 304 // sending typing notification
#define FACEBOOK_REQUEST_VISIBILITY 305 // setting chat visibility
-#define FACEBOOK_REQUEST_TABS 306 // closing message window, setting chat visibility
+#define FACEBOOK_REQUEST_TABS 306 // closing message window
#define FACEBOOK_REQUEST_ASYNC 307 // marking messages read and getting other things
-#define FACEBOOK_REQUEST_ASYNC_GET 308 // GET version of async request
#define FACEBOOK_RECV_MESSAGE 1
#define FACEBOOK_SEND_MESSAGE 2
@@ -116,10 +113,10 @@ static const struct
const char *name;
const char *id;
} feed_types[] = {
- { "Most Recent", "lf" },
- { "Status Updates", "app_2915120374" },
- { "Top News", "h" },
+ { "Most Recent", "lf_" }, //h_chr?
+ { "Wall Posts", "app_2915120374" },
+ { "Top News", "h_nor" }, //h
{ "Photos", "app_2305272732_2392950137" },
{ "Links", "app_2309869772" },
-
+ { "Apps and Games", "appsandgames" },
}; \ No newline at end of file
diff --git a/FacebookRM/contacts.cpp b/FacebookRM/contacts.cpp
index 0b50411..2a2cf4b 100644
--- a/FacebookRM/contacts.cpp
+++ b/FacebookRM/contacts.cpp
@@ -82,11 +82,13 @@ HANDLE FacebookProto::AddToContactList(facebook_user* fbu, bool dont_check, cons
{
DBWriteContactSettingString(hContact,m_szModuleName,FACEBOOK_KEY_ID,fbu->user_id.c_str());
- std::string homepage = FACEBOOK_URL_PROFILE;
- homepage += fbu->user_id;
- DBWriteContactSettingString(hContact,m_szModuleName,"Homepage",homepage.c_str());
+ std::string homepage = FACEBOOK_URL_PROFILE + fbu->user_id;
+ DBWriteContactSettingString(hContact, m_szModuleName,"Homepage", homepage.c_str());
+
+ DBWriteContactSettingString(hContact, m_szModuleName, "MirVer", FACEBOOK_NAME);
DBDeleteContactSetting(hContact, "CList", "MyHandle");
+
DBVARIANT dbv;
if( !DBGetContactSettingTString(NULL,m_szModuleName,FACEBOOK_KEY_DEF_GROUP,&dbv) )
{
@@ -135,18 +137,17 @@ void FacebookProto::DeleteContactFromServer(void *data)
if ( data == NULL )
return;
- std::string *id = (std::string*)data;
+ std::string id = (*(std::string*)data);
+ delete data;
std::string query = "norefresh=false&post_form_id_source=AsyncRequest&lsd=&fb_dtsg=";
query += facy.dtsg_;
query += "&post_form_id=";
query += facy.post_form_id_;
query += "&uid=";
- query += *id;
+ query += id;
query += "&__user=";
- query += facy.self_.user_id;
-
- delete data;
+ query += facy.self_.user_id;
// Get unread inbox threads
http::response resp = facy.flap( FACEBOOK_REQUEST_DELETE_FRIEND, &query );
@@ -154,12 +155,26 @@ void FacebookProto::DeleteContactFromServer(void *data)
// Process result data
facy.validate_response(&resp);
- if (resp.code != HTTP_CODE_OK) {
- facy.handle_error( "DeleteContactFromServer" );
+ if (resp.data.find("\"success\":true", 0) != std::string::npos) {
+
+ // TODO: do only when operation is successful
+ facebook_user* fbu = facy.buddies.find( id );
+ if (fbu != NULL) {
+ fbu->deleted = true;
+ // TODO: change type of contact in database...
+ DBWriteContactSettingWord(fbu->handle, m_szModuleName, "Status", ID_STATUS_OFFLINE); // set offline status
+
+ // TODO: if not in actual buddies list, search in database...
+ DBWriteContactSettingDword(fbu->handle, m_szModuleName, FACEBOOK_KEY_DELETED, ::time(NULL)); // set deleted time
+ }
+
+ NotifyEvent(TranslateT("Deleting contact"), TranslateT("Contact was sucessfully removed from server."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+ } else {
+ facy.client_notify( TranslateT("Error occured when removing contact from server.") );
}
- // TODO: better notify - check result code
- NotifyEvent(TranslateT("Deleting contact"), TranslateT("Contact was sucessfully removed from server."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+ if (resp.code != HTTP_CODE_OK)
+ facy.handle_error( "DeleteContactFromServer" );
}
void FacebookProto::AddContactToServer(void *data)
@@ -188,11 +203,21 @@ void FacebookProto::AddContactToServer(void *data)
// Process result data
facy.validate_response(&resp);
- if (resp.code != HTTP_CODE_OK || resp.data.find("\"success\":true") == std::string::npos) {
- facy.handle_error( "AddContactToServer" );
+ if (resp.data.find("\"success\":true", 0) != std::string::npos) {
+ /*facebook_user* fbu = facy.buddies.find( id );
+ if (fbu != NULL) {
+ // TODO: change type of contact in database...
+ // TODO: if not in actual buddies list, search in database...
+ }*/
+
+ NotifyEvent(TranslateT("Adding contact"), TranslateT("Request for friendship was sent successfully."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+ } else {
+ facy.client_notify( TranslateT("Error occured when requesting friendship.") );
}
-// RM TODO: better notify... - check result code
- NotifyEvent(TranslateT("Adding contact"), TranslateT("Request for friendship was sent successfully."), NULL, FACEBOOK_EVENT_OTHER, NULL);
+
+ if (resp.code != HTTP_CODE_OK)
+ facy.handle_error( "AddContactToServer" );
+
}
@@ -213,7 +238,7 @@ int FacebookProto::OnContactDeleted(WPARAM wparam,LPARAM)
} else if( !DBGetContactSettingTString(hContact,m_szModuleName,FACEBOOK_KEY_ID,&dbv) ) {
mir_sntprintf(text,SIZEOF(text),TranslateT("Do you want to delete contact '%s' from server list?"),dbv.ptszVal);
DBFreeVariant(&dbv);
- }
+ }
if (MessageBox( 0, text, m_tszUserName, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 ) == IDYES) {
@@ -221,20 +246,17 @@ int FacebookProto::OnContactDeleted(WPARAM wparam,LPARAM)
{
if (!isOffline()) { // TODO: is this needed?
std::string* id = new std::string(dbv.pszVal);
+
+ facebook_user* fbu = facy.buddies.find( (*id) );
+ if (fbu != NULL) {
+ fbu->handle = NULL;
+ }
+
ForkThread( &FacebookProto::DeleteContactFromServer, this, ( void* )id );
DBFreeVariant(&dbv);
}
}
- }
-
- //ScopedLock s(facy.buddies_lock_);
- for (List::Item< facebook_user >* i = facy.buddies.begin( ); i != NULL; i = i->next )
- {
- if (hContact == i->data->handle)
- {
- facy.buddies.erase(i->key);
- break;
- }
+
}
return 0;
diff --git a/FacebookRM/db.h b/FacebookRM/db.h
index 5efcefe..d928300 100644
--- a/FacebookRM/db.h
+++ b/FacebookRM/db.h
@@ -67,6 +67,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FACEBOOK_KEY_POLL_RATE "PollRate" // [HIDDEN]
#define FACEBOOK_KEY_TIMEOUTS_LIMIT "TimeoutsLimit" // [HIDDEN]
#define FACEBOOK_KEY_DISABLE_LOGOUT "DisableLogout" // [HIDDEN]
+#define FACEBOOK_KEY_VALIDATE_RESPONSE "ValidateResponse" // [HIDDEN] - 0 = standard, 1 = always, 2 = never
#define FACEBOOK_KEY_EVENT_NOTIFICATIONS_ENABLE "EventNotificationsEnable"
#define FACEBOOK_KEY_EVENT_FEEDS_ENABLE "EventFeedsEnable"
diff --git a/FacebookRM/entities.h b/FacebookRM/entities.h
index e6fea18..dbe32b8 100644
--- a/FacebookRM/entities.h
+++ b/FacebookRM/entities.h
@@ -34,6 +34,7 @@ struct facebook_user
std::string image_url;
+ bool deleted;
facebook_user( )
{
@@ -41,6 +42,7 @@ struct facebook_user
this->user_id = this->real_name = this->image_url = "";
this->status_id = ID_STATUS_OFFLINE;
this->gender = 0;
+ this->deleted = false;
}
facebook_user( facebook_user* fu )
@@ -51,6 +53,7 @@ struct facebook_user
this->status_id = fu->status_id;
this->user_id = fu->user_id;
this->gender = fu->gender;
+ this->deleted = fu->deleted;
}
};
diff --git a/FacebookRM/events.cpp b/FacebookRM/events.cpp
index 967d878..2f93a58 100644
--- a/FacebookRM/events.cpp
+++ b/FacebookRM/events.cpp
@@ -48,16 +48,11 @@ LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
TCHAR* data = (TCHAR*)PUGetPluginData(hwnd);
if (data != NULL)
{
-// char *url = mir_t2a_cp(data,CP_UTF8);
- std::string url2 = mir_t2a_cp(data,CP_UTF8);
- std::string url = "http://www.facebook.com";
- if ( url2.substr(0,4) != "http" )
- {
- url.append(url2);
- CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) url.c_str() );
- } else {
- CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) url2.c_str() );
- }
+ std::string url = mir_t2a_cp(data,CP_UTF8);
+ if ( url.substr(0,4) != "http" )
+ url = FACEBOOK_URL_HOMEPAGE + url; // make absolute url
+
+ CallService(MS_UTILS_OPENURL, (WPARAM) 1, (LPARAM) url.c_str() );
}
// After a click, destroy popup
diff --git a/FacebookRM/facebook.rc b/FacebookRM/facebook.rc
index 4004191..7f66333 100644
--- a/FacebookRM/facebook.rc
+++ b/FacebookRM/facebook.rc
@@ -255,7 +255,7 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,0,8,0
+ FILEVERSION 0,0,8,1
PRODUCTVERSION 0,9,43,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
@@ -272,7 +272,7 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "Facebook protocol plugin for Miranda IM"
- VALUE "FileVersion", "0.0.8.0"
+ VALUE "FileVersion", "0.0.8.1"
VALUE "InternalName", "Facebook RM"
VALUE "LegalCopyright", "Copyright © 2009-2011 Michal Zelinka, 2011-2012 Robert Pösel"
VALUE "OriginalFilename", "facebook.dll"
diff --git a/FacebookRM/facebook_10.vcxproj.filters b/FacebookRM/facebook_10.vcxproj.filters
index 5239871..df7e784 100644
--- a/FacebookRM/facebook_10.vcxproj.filters
+++ b/FacebookRM/facebook_10.vcxproj.filters
@@ -83,9 +83,6 @@
<ClInclude Include="avatars.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="build.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="client.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -119,15 +116,18 @@
<ClInclude Include="proto.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="theme.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
+ <ClInclude Include="theme.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="build.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="JSON_CAJUN\elements.inl">
diff --git a/FacebookRM/json.cpp b/FacebookRM/json.cpp
index 93fa30e..4293f33 100644
--- a/FacebookRM/json.cpp
+++ b/FacebookRM/json.cpp
@@ -140,83 +140,6 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use
return EXIT_SUCCESS;
}
-int facebook_json_parser::parse_facepiles( void* data, std::map< std::string, std::string > *facepiles )
-{
- using namespace json;
-
- try
- {
- std::string buddyData = static_cast< std::string* >( data )->substr( 9 );
- std::istringstream sDocument( buddyData );
- Object objDocument;
- Reader::Read(objDocument, sDocument);
- std::map< std::string, std::string >::iterator it;
-
- const Object& objRoot = objDocument;
-/* const Array& infos = objRoot["payload"]["facepile_click_info"];
-
- for ( Array::const_iterator info( infos.Begin() );
- info != infos.End(); ++info)
- {
- const Object& objMember = *info;
-
- if (objMember.Find("uid") != objMember.End()) {
- const Number& id = objMember["uid"];
- char was_id[32];
- lltoa( id.Value(), was_id, 10 );
-
- const String& name = objMember["name"];
- std::string user_name = utils::text::slashu_to_utf8(
- utils::text::special_expressions_decode( name.Value() ) );
-
- it = facepiles->find( std::string( was_id ) );
- if ( it == facepiles->end() ) {
- facepiles->insert( std::make_pair( was_id, user_name ) );
- }
- }
- } */
-
- // Contacts in chat are getting by parsing html response. Don't know if it will work also for many people in chat room.
- const String& response_html = objRoot["payload"]["response_html"];
- std::string contacts = utils::text::slashu_to_utf8( utils::text::special_expressions_decode( response_html.Value( ) ) );
-
- std::string::size_type pos = 0;
- while ((pos = contacts.find("<li", pos)) != std::string::npos) {
- std::string row = contacts.substr(pos, contacts.find("</li>") - pos);
-
- std::string status = utils::text::source_get_value2( &row, "chat", "\" " ); // "Online" or "Idle"
- std::string name = utils::text::source_get_value( &row, 2, "title=\"", "\"" );
- std::string id = utils::text::source_get_value( &row, 3, "href=\"", "/profile.php?id=", "\"" );
- if (id.empty())
- id = utils::text::source_get_value( &row, 3, "href=\"", "facebook.com/", "\"" );
-
- it = facepiles->find( id );
- if ( it == facepiles->end() ) {
- facepiles->insert( std::make_pair( id, name ) );
- }
-
- pos++;
- }
-
- }
- catch (Reader::ParseException& e)
- {
- proto->Log( "!!!!! Caught json::ParseException: %s", e.what() );
- proto->Log( " Line/offset: %d/%d", e.m_locTokenBegin.m_nLine + 1, e.m_locTokenBegin.m_nLineOffset + 1 );
- }
- catch (const Exception& e)
- {
- proto->Log( "!!!!! Caught json::Exception: %s", e.what() );
- }
- catch (const std::exception& e)
- {
- proto->Log( "!!!!! Caught std::exception: %s", e.what() );
- }
-
- return EXIT_SUCCESS;
-}
-
-
int facebook_json_parser::parse_friends( void* data, std::map< std::string, facebook_user* >* friends )
{
using namespace json;
@@ -289,24 +212,27 @@ int facebook_json_parser::parse_notifications( void *data, std::vector< facebook
Reader::Read(objDocument, sDocument);
const Object& objRoot = objDocument;
- const Object& payload = objRoot["payload"]["markup_map"];
+ const Object& payload = objRoot["payload"]["notifications"];
for ( Object::const_iterator payload_item( payload.Begin() ); payload_item != payload.End(); ++payload_item)
{
const Object::Member& member = *payload_item;
+
+ const Object& objMember = member.element;
- const String& content = member.element;
-
+ const String& content = objMember["markup"];
+ const Number& unread = objMember["unread"];
+
+ if (unread.Value() == 0) // ignore old notifications
+ continue;
+
std::string text = utils::text::slashu_to_utf8(
utils::text::special_expressions_decode( content.Value() ) );
- if (text.find("jewelItemNew") == std::string::npos)
- continue; // we want only unread notifications
-
facebook_notification* notification = new facebook_notification( );
notification->text = utils::text::remove_html( utils::text::source_get_value(&text, 1, "<abbr") );
- notification->link = utils::text::source_get_value(&text, 2, "<a href=\"", "\"");
+ notification->link = utils::text::source_get_value(&text, 3, "<a ", "href=\"", "\"");
notifications->push_back( notification );
}
@@ -377,7 +303,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
facebook_message* message = new facebook_message( );
message->message_text = utils::text::special_expressions_decode(
utils::text::slashu_to_utf8( text.Value( ) ) );
- message->time = ::time( NULL );
+ message->time = ::time( NULL ); // TODO: use real time from facebook
message->user_id = was_id;
messages->push_back( message );
@@ -425,7 +351,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess
message->sender_name = utils::text::special_expressions_decode(
utils::text::slashu_to_utf8( sender_name.Value( ) ) );
- message->time = ::time( NULL );
+ message->time = ::time( NULL ); // TODO: user real time from facebook
message->user_id = was_id; // TODO: Check if we have contact with this ID in friendlist and then do something different?
if (row.find("uiSplitPic",0) != std::string::npos) {
diff --git a/FacebookRM/json.h b/FacebookRM/json.h
index e2a55b2..c83e1ef 100644
--- a/FacebookRM/json.h
+++ b/FacebookRM/json.h
@@ -31,7 +31,6 @@ class facebook_json_parser
public:
FacebookProto* proto;
int parse_buddy_list( void*, List::List< facebook_user >* );
- int parse_facepiles( void*, std::map< std::string, std::string >* );
int parse_friends( void*, std::map< std::string, facebook_user* >* );
int parse_notifications( void*, std::vector< facebook_notification* >* );
int parse_messages( void*, std::vector< facebook_message* >*, std::vector< facebook_notification* >* );
diff --git a/FacebookRM/messages.cpp b/FacebookRM/messages.cpp
index b4c6459..d6873d6 100644
--- a/FacebookRM/messages.cpp
+++ b/FacebookRM/messages.cpp
@@ -131,11 +131,12 @@ void FacebookProto::SendTypingWorker(void *p)
data += ( typing->status == PROTOTYPE_SELFTYPING_ON ) ? "1" : "0"; // PROTOTYPE_SELFTYPING_OFF
data += "&to=";
data += dbv.pszVal;
- data += "&source=chat";
+ data += "&source=mercury-chat";
data += "&fb_dtsg=" + facy.dtsg_;
data += "&post_form_id=";
data += ( facy.post_form_id_.length( ) ) ? facy.post_form_id_ : "0";
- data += "&post_form_id_source=AsyncRequest&lsd=";
+ data += "&post_form_id_source=AsyncRequest&lsd=&phstamp=0&__user=";
+ data += facy.self_.user_id;
http::response resp = facy.flap( FACEBOOK_REQUEST_TYPING_SEND, &data );
@@ -155,8 +156,8 @@ void FacebookProto::MessagingWorker(void *p)
if (data->type == FACEBOOK_RECV_MESSAGE)
facy.chat_mark_read( data->user_id );
- if ( DBGetContactSettingByte(NULL, m_szModuleName, FACEBOOK_KEY_CLOSE_WINDOWS_ENABLE, DEFAULT_CLOSE_WINDOWS_ENABLE ) )
- facy.close_chat( data->user_id );
+// if ( DBGetContactSettingByte(NULL, m_szModuleName, FACEBOOK_KEY_CLOSE_WINDOWS_ENABLE, DEFAULT_CLOSE_WINDOWS_ENABLE ) )
+// facy.close_chat( data->user_id );
delete data;
}
diff --git a/FacebookRM/process.cpp b/FacebookRM/process.cpp
index 6f1ea0d..4136e1b 100644
--- a/FacebookRM/process.cpp
+++ b/FacebookRM/process.cpp
@@ -48,11 +48,11 @@ void FacebookProto::ProcessBuddyList( void* data )
facebook_user* fbu;
- if ( i->data->status_id == ID_STATUS_OFFLINE )
+ if ( i->data->status_id == ID_STATUS_OFFLINE || i->data->deleted )
{
fbu = i->data;
- if (fbu->handle)
+ if (fbu->handle && !fbu->deleted)
DBWriteContactSettingWord(fbu->handle, m_szModuleName, "Status", ID_STATUS_OFFLINE);
std::string to_delete( i->key );
@@ -109,66 +109,6 @@ exit:
delete resp;
}
-void FacebookProto::ProcessFacepiles( void* data )
-{
- if ( data == NULL )
- return;
-
- send_chat *resp = static_cast<send_chat*>(data);
-
- if ( isOffline() )
- goto exit;
-
- LOG("***** Starting processing facepiles");
-
- CODE_BLOCK_TRY
-
- std::map< std::string, std::string > facepiles;
-
- facebook_json_parser* p = new facebook_json_parser( this );
- p->parse_facepiles( &(resp->msg), &facepiles );
- delete p;
-
- std::map< std::string, std::string >::iterator iter;
-
- char *chat_users = this->GetChatUsers(resp->chat_id.c_str());
- std::string users = chat_users;
- mir_free(chat_users);
-
- std::vector<std::string> users_list;
- utils::text::explode(users, " ", &users_list);
-
- for( std::vector<std::string>::size_type i=0; i<users_list.size( ); i++) {
- iter = facepiles.find( users_list[i] );
- if (iter == facepiles.end()) {
- // Contact is now offline, remove him from chat
- this->RemoveChatContact(resp->chat_id.c_str(), users_list[i].c_str());
- LOG(" Now offline facepile (%s): [%s]", resp->chat_id.c_str(), users_list[i].c_str());
- } else {
- facepiles.erase(iter);
- }
- }
-
- for ( iter = facepiles.begin( ); iter != facepiles.end(); ++iter )
- {
- // These contacts are newly online, add them...
- this->AddChatContact(resp->chat_id.c_str(), iter->first.c_str(), iter->second.c_str());
- LOG(" Now online facepile (%s): [%s] %s", resp->chat_id.c_str(), iter->first.c_str(), iter->second.c_str());
- }
-
- LOG("***** Facepiles processed");
-
- CODE_BLOCK_CATCH
-
- LOG("***** Error processing facepiles: %s", e.what());
-
- CODE_BLOCK_END
-
-exit:
- delete resp;
-}
-
-
void FacebookProto::ProcessFriendList( void* data )
{
if ( data == NULL )
@@ -214,7 +154,16 @@ void FacebookProto::ProcessFriendList( void* data )
// - but what with contacts, that was added after logon?
// Update gender
if ( DBGetContactSettingByte(hContact, m_szModuleName, "Gender", 0) != fbu->gender )
- DBWriteContactSettingByte(hContact, m_szModuleName, "Gender", fbu->gender );
+ DBWriteContactSettingByte(hContact, m_szModuleName, "Gender", fbu->gender);
+
+ // TODO: Remove in next version
+ if( !DBGetContactSettingString(hContact, m_szModuleName, "MirVer", &dbv) ) {
+ update_required = strcmp( dbv.pszVal, FACEBOOK_NAME ) != 0;
+ DBFreeVariant(&dbv);
+ }
+ if (update_required) {
+ DBWriteContactSettingString(hContact, m_szModuleName, "MirVer", FACEBOOK_NAME);
+ }
// Update real name
if ( !DBGetContactSettingUTF8String(hContact, m_szModuleName, FACEBOOK_KEY_NAME, &dbv) )
@@ -256,7 +205,7 @@ void FacebookProto::ProcessFriendList( void* data )
// Wasnt we already been notified about this contact?
if ( !DBGetContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, 0)
&& !DBGetContactSettingByte(hContact, m_szModuleName, FACEBOOK_KEY_CONTACT_TYPE, 0) ) { // And is this contact "on-server" contact?
-
+
DBWriteContactSettingDword(hContact, m_szModuleName, FACEBOOK_KEY_DELETED, ::time(NULL));
std::string contactname = id;
@@ -306,13 +255,23 @@ void FacebookProto::ProcessUnreadMessages( void* )
{
facy.handle_entry( "messages" );
- std::string data = "sk=inbox&query=is%3Aunread";
+ std::string get_data = "sk=inbox&query=is%3Aunread";
+
+ std::string data = "post_form_id=";
+ data += ( facy.post_form_id_.length( ) ) ? facy.post_form_id_ : "0";
+ data += "&fb_dtsg=" + facy.dtsg_;
+ data += "&post_form_id_source=AsyncRequest&lsd=&phstamp=";
+ data += utils::time::mili_timestamp();
+ data += "&__user=";
+ data += facy.self_.user_id;
// Get unread inbox threads
- http::response resp = facy.flap( FACEBOOK_REQUEST_ASYNC_GET, &data );
+ http::response resp = facy.flap( FACEBOOK_REQUEST_ASYNC, &data, &get_data );
+
+ // sk=inbox, sk=other
// Process result data
- facy.validate_response(&resp);
+ facy.validate_response(&resp);
if (resp.code != HTTP_CODE_OK) {
facy.handle_error( "messages" );
@@ -325,15 +284,16 @@ void FacebookProto::ProcessUnreadMessages( void* )
while ( ( pos = threadlist.find( "<li class=\\\"threadRow noDraft unread", pos ) ) != std::string::npos )
{
- std::string::size_type pos2 = threadlist.find( "<\\/li", pos );
+ std::string::size_type pos2 = threadlist.find( "/li>", pos );
std::string thread_content = threadlist.substr( pos, pos2 - pos );
pos = pos2;
- data = "sk=inbox&query=is%3Aunread&thread_query=is%3Aunread&action=read&tid=";
- data += utils::text::source_get_value( &thread_content, 2, "id=\\\"", "\\\"" );
+ get_data = "sk=inbox&query=is%3Aunread&thread_query=is%3Aunread&action=read&tid=";
+ get_data += utils::text::source_get_value( &thread_content, 2, "id=\\\"", "\\\"" );
- resp = facy.flap( FACEBOOK_REQUEST_ASYNC_GET, &data );
+ resp = facy.flap( FACEBOOK_REQUEST_ASYNC, &data, &get_data );
+ // TODO: move this to new thread...
facy.validate_response(&resp);
@@ -342,7 +302,7 @@ void FacebookProto::ProcessUnreadMessages( void* )
continue;
}
- std::string messageslist = utils::text::slashu_to_utf8(resp.data);
+ std::string messageslist = utils::text::slashu_to_utf8(resp.data);
std::string user_id = utils::text::source_get_value( &messageslist, 2, "single_thread_id\":", "," );
if (user_id.empty()) {
@@ -350,38 +310,96 @@ void FacebookProto::ProcessUnreadMessages( void* )
continue;
}
- messageslist = utils::text::source_get_value( &messageslist, 3, "class=\\\"MessagingMessage", "MessagingMessageUnread", "class=\\\"MessagingComposer" );
-
facebook_user fbu;
fbu.user_id = user_id;
HANDLE hContact = AddToContactList(&fbu);
+ // TODO: if contact is newly added, get his user info
+ // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages?
- pos2 = 0;
- while ( ( pos2 = messageslist.find( "class=\\\"content noh", pos2 ) ) != std::string::npos )
- {
- std::string message_text;
- message_text = messageslist.substr(pos2, messageslist.find( "<\\/div", pos2) + 6 - pos2);
- message_text = utils::text::source_get_value( &message_text, 2, "\\\">", "<\\/div" );
- message_text = utils::text::trim(
- utils::text::special_expressions_decode(
- utils::text::remove_html( message_text ) ) );
+ pos2 = 0;
+ while ( ( pos2 = messageslist.find( "class=\\\"MessagingMessage ", pos2 ) ) != std::string::npos ) {
+ pos2 += 8;
+ std::string strclass = messageslist.substr(pos2, messageslist.find("\\\"", pos2) - pos2);
- PROTORECVEVENT recv = {0};
- CCSDATA ccs = {0};
+ if (strclass.find("MessagingMessageUnread") == std::string::npos)
+ continue; // ignoring old messages
- recv.flags = PREF_UTF;
- recv.szMessage = const_cast<char*>(message_text.c_str());
- recv.timestamp = static_cast<DWORD>(::time(NULL));
+ //std::string::size_type pos3 = messageslist.find( "/li>", pos2 ); // TODO: ne proti tomuhle li, protože i přílohy mají li...
+ std::string::size_type pos3 = messageslist.find( "class=\\\"MessagingMessage ", pos2 );
+ std::string messagesgroup = messageslist.substr( pos2, pos3 - pos2 );
- ccs.hContact = hContact;
- ccs.szProtoService = PSR_MESSAGE;
- ccs.lParam = reinterpret_cast<LPARAM>(&recv);
- CallService(MS_PROTO_CHAINRECV,0,reinterpret_cast<LPARAM>(&ccs));
+ DWORD timestamp = NULL;
+ std::string strtime = utils::text::source_get_value( &messagesgroup, 2, "data-utime=\\\"", "\\\"" );
+ if (!utils::conversion::from_string<DWORD>(timestamp, strtime, std::dec)) {
+ timestamp = static_cast<DWORD>(::time(NULL));
+ }
- pos2++;
- }
+ pos3 = 0;
+ while ( ( pos3 = messagesgroup.find( "class=\\\"content noh", pos3 ) ) != std::string::npos )
+ {
+
+ std::string message_attachments = "";
+ std::string::size_type pos4 = 0;
+ if ((pos4 = messagesgroup.find( "class=\\\"attachments\\\"", pos4)) != std::string::npos) {
+ std::string attachments = messagesgroup.substr( pos4, messagesgroup.find("<\\/ul", pos4) - pos4 );
+
+ pos4 = 0;
+ while ( ( pos4 = attachments.find("<li", pos4) ) != std::string::npos ) {
+ std::string attachment = attachments.substr( pos4, attachments.find("<\\/li>", pos4) - pos4 );
+ std::string link = utils::text::source_get_value( &attachment, 4, "<a class=", "attachment", "href=\\\"", "\\\"" );
+
+ link = utils::text::trim(
+ utils::text::special_expressions_decode( link ) );
+ // or first: std::string name = utils::text::source_get_value( &attachment, 4, "<a class=", "attachment", ">", "<\\/a>" );
+ std::string name = utils::text::trim(
+ utils::text::special_expressions_decode(
+ utils::text::remove_html( attachment ) ) );
+
+ if (link.find("/ajax/messaging/attachments/photo/dialog.php?uri=") != std::string::npos) {
+ link = link.substr(49);
+ link = utils::url::decode(link);
+ }
+
+ message_attachments += "< " + name + " > " + FACEBOOK_URL_HOMEPAGE;
+ message_attachments += link + "\r\n";
+
+ pos4++;
+ }
+
+ }
+
+ std::string message_text = messagesgroup.substr(pos3, messagesgroup.find( "<\\/div", pos3 ) + 6 - pos3);
+ message_text = utils::text::source_get_value( &message_text, 2, "\\\">", "<\\/div" );
+ message_text = utils::text::trim(
+ utils::text::special_expressions_decode(
+ utils::text::remove_html( message_text ) ) );
+
+ if (!message_attachments.empty()) {
+ if (!message_text.empty())
+ message_text += "\r\n\r\n";
+
+ message_text += Translate("Attachments:");
+ message_text += "\r\n" + message_attachments;
+ }
+
+ PROTORECVEVENT recv = {0};
+ CCSDATA ccs = {0};
+
+ recv.flags = PREF_UTF;
+ recv.szMessage = const_cast<char*>(message_text.c_str());
+ recv.timestamp = timestamp;
+
+ ccs.hContact = hContact;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.lParam = reinterpret_cast<LPARAM>(&recv);
+ CallService(MS_PROTO_CHAINRECV,0,reinterpret_cast<LPARAM>(&ccs));
+
+ pos3++;
+ }
+
+ }
}
@@ -418,6 +436,9 @@ void FacebookProto::ProcessMessages( void* data )
HANDLE hContact = AddToContactList(&fbu, false, messages[i]->sender_name.c_str());
+ // TODO: if contact is newly added, get his user info
+ // TODO: maybe create new "receiveMsg" function and use it for offline and channel messages?
+
PROTORECVEVENT recv = {0};
CCSDATA ccs = {0};
diff --git a/FacebookRM/proto.cpp b/FacebookRM/proto.cpp
index 12dfd27..692de07 100644
--- a/FacebookRM/proto.cpp
+++ b/FacebookRM/proto.cpp
@@ -226,16 +226,6 @@ void FacebookProto::SetAwayMsgWorker(void *)
//////////////////////////////////////////////////////////////////////////////
// SERVICES
-int FacebookProto::GetStatus( WPARAM wParam, LPARAM lParam )
-{
- return m_iStatus;
-}
-
-int FacebookProto::SetStatus( WPARAM wParam, LPARAM lParam )
-{
- return SetStatus( (int)wParam );
-}
-
int FacebookProto::GetMyAwayMsg( WPARAM wParam, LPARAM lParam )
{
DBVARIANT dbv = { DBVT_TCHAR };
@@ -296,12 +286,6 @@ int FacebookProto::OnEvent(PROTOEVENTTYPE event,WPARAM wParam,LPARAM lParam)
//////////////////////////////////////////////////////////////////////////////
// EVENTS
-int FacebookProto::GetName( WPARAM wParam, LPARAM lParam )
-{
- lstrcpynA(reinterpret_cast<char*>(lParam),m_szProtoName,wParam);
- return 0;
-}
-
int FacebookProto::SvcCreateAccMgrUI(WPARAM wParam,LPARAM lParam)
{
return (int)CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_FACEBOOKACCOUNT),
diff --git a/FacebookRM/proto.h b/FacebookRM/proto.h
index 037643a..db236b8 100644
--- a/FacebookRM/proto.h
+++ b/FacebookRM/proto.h
@@ -109,9 +109,6 @@ public:
////////////////////////
// Services
- int __cdecl GetName( WPARAM, LPARAM );
- int __cdecl GetStatus( WPARAM, LPARAM );
- int __cdecl SetStatus( WPARAM, LPARAM );
int __cdecl GetMyAwayMsg( WPARAM, LPARAM );
int __cdecl SetMyAwayMsg( WPARAM, LPARAM );
int __cdecl SvcCreateAccMgrUI( WPARAM, LPARAM );
@@ -143,7 +140,6 @@ public:
// Processing threads
void __cdecl ProcessBuddyList(void*);
- void __cdecl ProcessFacepiles(void*);
void __cdecl ProcessFriendList(void*);
void __cdecl ProcessMessages(void*);
void __cdecl ProcessUnreadMessages(void*);
diff --git a/FacebookRM/utils.cpp b/FacebookRM/utils.cpp
index 02a7662..5440757 100644
--- a/FacebookRM/utils.cpp
+++ b/FacebookRM/utils.cpp
@@ -32,6 +32,17 @@ std::string utils::url::encode(const std::string &s)
return ret;
}
+std::string utils::url::decode(std::string data)
+{
+ // TODO: Better and universal method?
+ utils::text::replace_all( &data, "%2F", "/" );
+ utils::text::replace_all( &data, "%3F", "?" );
+ utils::text::replace_all( &data, "%3D", "=" );
+ utils::text::replace_all( &data, "%26", "&" );
+
+ return data;
+}
+
std::string utils::time::unix_timestamp( )
{
time_t in = ::time( NULL );
diff --git a/FacebookRM/utils.h b/FacebookRM/utils.h
index 6d9acb5..868aeb8 100644
--- a/FacebookRM/utils.h
+++ b/FacebookRM/utils.h
@@ -65,6 +65,7 @@ namespace utils
namespace url
{
std::string encode(const std::string &s);
+ std::string decode(std::string data);
};
namespace time
@@ -96,6 +97,12 @@ namespace utils
namespace conversion
{
std::string to_string( void*, WORD type );
+
+ template <class T>
+ bool from_string(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&)) {
+ std::istringstream iss(s);
+ return !(iss >> f >> t).fail();
+ }
};
namespace debug