PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/dumbhippo/branches/cluster/client/windows/HippoUI/HippoPlatformImpl.cpp

https://gitlab.com/manoj-makkuboy/magnetism
C++ | 385 lines | 293 code | 82 blank | 10 comment | 21 complexity | 63d928a89beb63ef99c70fd6990dfbbf MD5 | raw file
  1. #include "stdafx-hippoui.h"
  2. #include "HippoPlatformImpl.h"
  3. #include "HippoUIUtil.h"
  4. #include <HippoUtil.h>
  5. #include <Windows.h>
  6. #include <mshtml.h>
  7. #include <hippo/hippo-basics.h>
  8. static void hippo_platform_impl_init (HippoPlatformImpl *impl);
  9. static void hippo_platform_impl_class_init (HippoPlatformImplClass *klass);
  10. static void hippo_platform_impl_iface_init (HippoPlatformClass *klass);
  11. static void hippo_platform_impl_finalize (GObject *object);
  12. static gboolean hippo_platform_impl_read_login_cookie (HippoPlatform *platform,
  13. HippoBrowserKind *origin_browser_p,
  14. char **username_p,
  15. char **password_p);
  16. static void hippo_platform_impl_delete_login_cookie (HippoPlatform *platform);
  17. static const char* hippo_platform_impl_get_jabber_resource (HippoPlatform *platform);
  18. static char* hippo_platform_impl_get_message_server (HippoPlatform *platform);
  19. static char* hippo_platform_impl_get_web_server (HippoPlatform *platform);
  20. static gboolean hippo_platform_impl_get_signin (HippoPlatform *platform);
  21. static void hippo_platform_impl_set_message_server (HippoPlatform *platform,
  22. const char *value);
  23. static void hippo_platform_impl_set_web_server (HippoPlatform *platform,
  24. const char *value);
  25. static void hippo_platform_impl_set_signin (HippoPlatform *platform,
  26. gboolean value);
  27. struct _HippoPlatformImpl {
  28. GObject parent;
  29. HippoInstanceType instance;
  30. char *jabber_resource;
  31. HippoPreferences *preferences;
  32. };
  33. struct _HippoPlatformImplClass {
  34. GObjectClass parent_class;
  35. };
  36. G_DEFINE_TYPE_WITH_CODE(HippoPlatformImpl, hippo_platform_impl, G_TYPE_OBJECT,
  37. G_IMPLEMENT_INTERFACE(HIPPO_TYPE_PLATFORM, hippo_platform_impl_iface_init));
  38. static void
  39. hippo_platform_impl_iface_init(HippoPlatformClass *klass)
  40. {
  41. klass->read_login_cookie = hippo_platform_impl_read_login_cookie;
  42. klass->delete_login_cookie = hippo_platform_impl_delete_login_cookie;
  43. klass->get_jabber_resource = hippo_platform_impl_get_jabber_resource;
  44. klass->get_message_server = hippo_platform_impl_get_message_server;
  45. klass->get_web_server = hippo_platform_impl_get_web_server;
  46. klass->get_signin = hippo_platform_impl_get_signin;
  47. klass->set_message_server = hippo_platform_impl_set_message_server;
  48. klass->set_web_server = hippo_platform_impl_set_web_server;
  49. klass->set_signin = hippo_platform_impl_set_signin;
  50. }
  51. static void
  52. hippo_platform_impl_init(HippoPlatformImpl *impl)
  53. {
  54. }
  55. static void
  56. hippo_platform_impl_class_init(HippoPlatformImplClass *klass)
  57. {
  58. GObjectClass *object_class = G_OBJECT_CLASS(klass);
  59. object_class->finalize = hippo_platform_impl_finalize;
  60. }
  61. HippoPlatform*
  62. hippo_platform_impl_new(HippoInstanceType instance)
  63. {
  64. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(g_object_new(HIPPO_TYPE_PLATFORM_IMPL, NULL));
  65. impl->instance = instance;
  66. impl->preferences = new HippoPreferences(instance);
  67. return HIPPO_PLATFORM(impl);
  68. }
  69. static void
  70. hippo_platform_impl_finalize(GObject *object)
  71. {
  72. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(object);
  73. g_free(impl->jabber_resource);
  74. delete impl->preferences;
  75. G_OBJECT_CLASS(hippo_platform_impl_parent_class)->finalize(object);
  76. }
  77. HippoPreferences*
  78. hippo_platform_impl_get_preferences(HippoPlatformImpl *impl)
  79. {
  80. g_return_val_if_fail(HIPPO_IS_PLATFORM_IMPL(impl), NULL);
  81. return impl->preferences;
  82. }
  83. static bool
  84. startsWith(WCHAR *str, WCHAR *prefix)
  85. {
  86. size_t prefixlen = wcslen(prefix);
  87. return wcsncmp(str, prefix, prefixlen) == 0;
  88. }
  89. static void
  90. copySubstring(WCHAR *str, WCHAR *end, BSTR *to)
  91. {
  92. unsigned int length = (unsigned int)(end - str);
  93. HippoBSTR tmp(length, str);
  94. tmp.CopyTo(to);
  95. }
  96. static void
  97. makeAuthUrl(const char *web_host,
  98. BSTR *authUrl)
  99. {
  100. // we're getting the cookies we would send to this url if we were
  101. // sending this url an HTTP request. We ignore the web_port stuff
  102. // since browser behavior is unpredictable then, we just assume
  103. // all servers have their own hostname here and elsewhere.
  104. HippoBSTR tmp(L"http://");
  105. tmp.appendUTF8(web_host, -1);
  106. tmp.Append(L"/");
  107. tmp.CopyTo(authUrl);
  108. }
  109. static void
  110. getAuthUrl(HippoPlatform *platform,
  111. BSTR *authUrl)
  112. {
  113. char *web_host;
  114. int web_port;
  115. hippo_platform_get_web_host_port(platform, &web_host, &web_port);
  116. makeAuthUrl(web_host, authUrl);
  117. g_free(web_host);
  118. }
  119. static gboolean
  120. do_read_login_cookie(const char *web_host,
  121. char **username_p,
  122. char **password_p)
  123. {
  124. WCHAR staticBuffer[1024];
  125. WCHAR *allocBuffer = NULL;
  126. WCHAR *cookieBuffer = staticBuffer;
  127. DWORD cookieSize = sizeof(staticBuffer) / sizeof(staticBuffer[0]);
  128. char *cookie = NULL;
  129. HippoBSTR authUrl;
  130. *username_p = NULL;
  131. *password_p = NULL;
  132. makeAuthUrl(web_host, &authUrl);
  133. retry:
  134. if (!InternetGetCookieEx(authUrl,
  135. L"auth",
  136. cookieBuffer, &cookieSize,
  137. 0,
  138. NULL))
  139. {
  140. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  141. cookieBuffer = allocBuffer = new WCHAR[cookieSize];
  142. if (!cookieBuffer)
  143. goto out;
  144. goto retry;
  145. }
  146. }
  147. WCHAR *p = cookieBuffer;
  148. WCHAR *nextCookie = NULL;
  149. for (WCHAR *p = cookieBuffer; p < cookieBuffer + cookieSize; p = nextCookie + 1) {
  150. HippoBSTR host;
  151. HippoBSTR username;
  152. HippoBSTR password;
  153. nextCookie = wcschr(p, ';');
  154. if (!nextCookie)
  155. nextCookie = cookieBuffer + cookieSize;
  156. while (*p == ' ' || *p == '\t') // Skip whitespace after ;
  157. p++;
  158. if (!startsWith(p, L"auth="))
  159. continue;
  160. p += 5; // Skip 'auth='
  161. HippoUStr cookieValue(p, (int) (nextCookie - p));
  162. if (hippo_parse_login_cookie(cookieValue.c_str(),
  163. web_host, username_p, password_p))
  164. break;
  165. }
  166. out:
  167. delete[] allocBuffer;
  168. return (*username_p && *password_p);
  169. }
  170. static gboolean
  171. hippo_platform_impl_read_login_cookie(HippoPlatform *platform,
  172. HippoBrowserKind *origin_browser_p,
  173. char **username_p,
  174. char **password_p)
  175. {
  176. char *web_host;
  177. int web_port;
  178. *origin_browser_p = HIPPO_BROWSER_IE;
  179. hippo_platform_get_web_host_port(platform, &web_host, &web_port);
  180. g_debug("Looking for login to %s:%d", web_host, web_port);
  181. gboolean result = do_read_login_cookie(web_host, username_p, password_p);
  182. g_free(web_host);
  183. return result;
  184. }
  185. static void
  186. hippo_platform_impl_delete_login_cookie(HippoPlatform *platform)
  187. {
  188. HippoBSTR authUrl;
  189. getAuthUrl(platform, &authUrl);
  190. InternetSetCookie(authUrl, NULL, L"auth=; Path=/");
  191. }
  192. void
  193. hippo_platform_impl_windows_migrate_cookie(const char *from_web_host,
  194. const char *to_web_host)
  195. {
  196. char *username;
  197. char *password;
  198. // See if we already have a cookie from the new host
  199. if (do_read_login_cookie(to_web_host, &username, &password)) {
  200. g_free(username);
  201. g_free(password);
  202. return;
  203. }
  204. if (!do_read_login_cookie(from_web_host, &username, &password))
  205. return;
  206. GDate *date = g_date_new();
  207. GTimeVal timeval;
  208. g_get_current_time(&timeval);
  209. g_date_set_time_val(date, &timeval);
  210. g_date_add_days(date, 5 * 365); // 5 years, more or less
  211. // Can't use g_date_strftime, since that would be unpredictably located
  212. // while we need fixed english-locale DAY, DD-MMM-YYYY HH:MM:SS GMT
  213. static const char *days[] = {
  214. "Mon", "Tue", "Wed", "The", "Fri", "Sat", "Sun"
  215. };
  216. static const char * const months[] = {
  217. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  218. };
  219. char *cookieUTF8 = g_strdup_printf("auth=host=%s&name=%s&password=%s; Path=/; expires = %s, %02d-%s-%04d 00:00:00 GMT",
  220. to_web_host,
  221. username,
  222. password,
  223. days[(int)g_date_get_weekday(date) - 1],
  224. g_date_get_day(date),
  225. months[(int)g_date_get_month(date) - 1],
  226. g_date_get_year(date));
  227. g_date_free(date);
  228. HippoBSTR cookie;
  229. cookie.setUTF8(cookieUTF8, -1);
  230. g_free(cookieUTF8);
  231. HippoBSTR authUrl;
  232. makeAuthUrl(to_web_host, &authUrl);
  233. InternetSetCookie(authUrl, NULL, cookie);
  234. g_free(username);
  235. g_free(password);
  236. }
  237. static const char*
  238. hippo_platform_impl_get_jabber_resource(HippoPlatform *platform)
  239. {
  240. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  241. if (impl->jabber_resource == NULL) {
  242. // Create an XMPP resource identifier based on this machine's hardware
  243. // profile GUID.
  244. HW_PROFILE_INFO hwProfile;
  245. if (GetCurrentHwProfile(&hwProfile)) {
  246. HippoUStr guidUTF(hwProfile.szHwProfileGuid);
  247. impl->jabber_resource = g_strdup(guidUTF.c_str());
  248. } else {
  249. hippoDebugLogW(L"Failed to get hardware profile!");
  250. // uhhh... let's just make up a number, better than bombing out
  251. GTimeVal val;
  252. g_get_current_time(&val);
  253. impl->jabber_resource = g_strdup_printf("%d", val.tv_sec);
  254. }
  255. g_debug("jabber resource: '%s'", impl->jabber_resource);
  256. }
  257. return impl->jabber_resource;
  258. }
  259. static char*
  260. hippo_platform_impl_get_message_server(HippoPlatform *platform)
  261. {
  262. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  263. HippoBSTR messageServer;
  264. impl->preferences->getMessageServer(&messageServer);
  265. HippoUStr messageServerUTF(messageServer);
  266. return g_strdup(messageServerUTF.c_str());
  267. }
  268. static char*
  269. hippo_platform_impl_get_web_server(HippoPlatform *platform)
  270. {
  271. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  272. HippoBSTR webServer;
  273. impl->preferences->getWebServer(&webServer);
  274. HippoUStr webServerUTF(webServer);
  275. return g_strdup(webServerUTF.c_str());
  276. }
  277. static gboolean
  278. hippo_platform_impl_get_signin(HippoPlatform *platform)
  279. {
  280. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  281. return impl->preferences->getSignIn();
  282. }
  283. static void
  284. hippo_platform_impl_set_message_server(HippoPlatform *platform,
  285. const char *value)
  286. {
  287. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  288. impl->preferences->setMessageServer(HippoBSTR::fromUTF8(value, -1));
  289. }
  290. static void
  291. hippo_platform_impl_set_web_server(HippoPlatform *platform,
  292. const char *value)
  293. {
  294. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  295. impl->preferences->setWebServer(HippoBSTR::fromUTF8(value, -1));
  296. }
  297. static void
  298. hippo_platform_impl_set_signin(HippoPlatform *platform,
  299. gboolean value)
  300. {
  301. HippoPlatformImpl *impl = HIPPO_PLATFORM_IMPL(platform);
  302. impl->preferences->setSignIn(value != FALSE);
  303. }