Index: chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc |
=================================================================== |
--- chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc (revision 0) |
+++ chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc (revision 0) |
@@ -0,0 +1,236 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/sync/notifier/gaia_auth/gaiahelper.h" |
+#include "talk/base/common.h" |
+#include "talk/base/cryptstring.h" |
+#include "talk/base/httpclient.h" |
+#include "talk/base/httpcommon-inl.h" |
+#include "talk/base/stringutils.h" |
+#include "talk/base/urlencode.h" |
+#include "talk/xmpp/constants.h" |
+#include "talk/xmpp/jid.h" |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+namespace { |
+ |
+std::string GetValueForKey(const std::string & key, const std::string & nvp) { |
+ size_t start_of_line = 0; |
+ size_t end_of_line = 0; |
+ for (;;) { // for each line |
+ start_of_line = nvp.find_first_not_of("\r\n", end_of_line); |
+ if (start_of_line == std::string::npos) |
+ break; |
+ end_of_line = nvp.find_first_of("\r\n", start_of_line); |
+ if (end_of_line == std::string::npos) { |
+ end_of_line = nvp.length(); |
+ } |
+ size_t equals = nvp.find('=', start_of_line); |
+ if (equals >= end_of_line || |
+ equals == std::string::npos || |
+ equals - start_of_line != key.length()) { |
+ continue; |
+ } |
+ |
+ if (nvp.find(key, start_of_line) == start_of_line) { |
+ return std::string(nvp, equals + 1, end_of_line - equals - 1); |
+ } |
+ } |
+ return ""; |
+} |
+ |
+} // anonymous namespace |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+namespace buzz { |
+ |
+GaiaServer::GaiaServer() |
+ : hostname_("www.google.com"), |
+ port_(443), |
+ use_ssl_(true) { |
+} |
+ |
+bool GaiaServer::SetServer(const char* url) { |
+ talk_base::Url<char> parsed(url); |
+ hostname_ = parsed.server(); |
+ port_ = parsed.port(); |
+ use_ssl_ = parsed.secure(); |
+ return true; // parsed.valid(); |
+} |
+ |
+bool GaiaServer::SetDebugServer(const char* server) { |
+ const char* colon = strchr(server, ':'); |
+ if (colon) { |
+ hostname_ = std::string(server, colon - server); |
+ port_ = atoi(colon+1); |
+ use_ssl_ = false; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+std::string GaiaServer::http_prefix() const { |
+ talk_base::Url<char> parsed("", hostname_, port_); |
+ parsed.set_secure(use_ssl_); |
+ return parsed.url(); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+bool GaiaRequestSid(talk_base::HttpClient* client, |
+ const std::string& username, |
+ const talk_base::CryptString& password, |
+ const std::string& signature, |
+ const std::string& service, |
+ const CaptchaAnswer& captcha_answer, |
+ const GaiaServer& gaia_server) { |
+ buzz::Jid jid(username); |
+ std::string usable_name = username; |
+ if (jid.domain() == buzz::STR_DEFAULT_DOMAIN) { |
+ // The default domain (default.talk.google.com) is not usable |
+ // for Gaia auth. But both gmail.com and googlemain.com will |
+ // work, because the gaia server doesn't check to make sure the |
+ // appropriate one is being used. So we just slam on gmail.com |
+ usable_name = jid.node() + "@" + buzz::STR_GMAIL_COM; |
+ } |
+ |
+ std::string post_data; |
+ post_data += "Email=" + UrlEncodeString(usable_name); |
+ post_data += "&Passwd=" + password.UrlEncode(); |
+ post_data += "&PersistentCookie=false"; |
+ post_data += "&source=" + signature; |
+ // TODO(chron): This behavior is not the same as in the other gaia auth |
+ // loader. We should make it the same. Probably GOOGLE is enough, we don't |
+ // want to auth against hosted accounts. |
+ post_data += "&accountType=HOSTED_OR_GOOGLE"; |
+ post_data += "&skipvpage=true"; |
+ if (!service.empty()) { |
+ post_data += "&service=" + service; |
+ } |
+ |
+ if (!captcha_answer.captcha_token().empty()) { |
+ post_data += "&logintoken=" + captcha_answer.captcha_token(); |
+ post_data += "&logincaptcha=" |
+ + UrlEncodeString(captcha_answer.captcha_answer()); |
+ } |
+ |
+ client->reset(); |
+ client->set_server(talk_base::SocketAddress(gaia_server.hostname(), |
+ gaia_server.port(), false)); |
+ client->request().verb = talk_base::HV_POST; |
+ client->request().path = "/accounts/ClientAuth"; |
+ client->request().setContent("application/x-www-form-urlencoded", |
+ new talk_base::MemoryStream(post_data.data(), post_data.size())); |
+ client->response().document.reset(new talk_base::MemoryStream); |
+ client->start(); |
+ return true; |
+} |
+ |
+GaiaResponse GaiaParseSidResponse(const talk_base::HttpClient& client, |
+ const GaiaServer& gaia_server, |
+ std::string* captcha_token, |
+ std::string* captcha_url, |
+ std::string* sid, |
+ std::string* lsid, |
+ std::string* auth) { |
+ uint32 status_code = client.response().scode; |
+ const talk_base::MemoryStream* stream = |
+ static_cast<const talk_base::MemoryStream*>( |
+ client.response().document.get()); |
+ size_t length; |
+ stream->GetPosition(&length); |
+ std::string response; |
+ if (length > 0) { |
+ response.assign(stream->GetBuffer(), length); |
+ } |
+ |
+ LOG(LS_INFO) << "GaiaAuth request to " << client.request().path; |
+ LOG(LS_INFO) << "GaiaAuth Status Code: " << status_code; |
+ LOG(LS_INFO) << response; |
+ |
+ if (status_code == talk_base::HC_FORBIDDEN) { |
+ // The error URL may be the relative path to the captcha jpg. |
+ std::string image_url = GetValueForKey("CaptchaUrl", response); |
+ if (!image_url.empty()) { |
+ // We should activate this "full url code" once we have a better ways |
+ // to crack the URL for later download. Right now we are too |
+ // dependent on what Gaia returns. |
+#if 0 |
+ if (image_url.find("http://") != 0 && |
+ image_url.find("https://") != 0) { |
+ if (image_url.find("/") == 0) { |
+ *captcha_url = gaia_server.http_prefix() + image_url; |
+ } else { |
+ *captcha_url = Utf8(gaia_server.http_prefix()).AsString() |
+ + "/accounts/" + image_url; |
+ } |
+ } |
+#else |
+ *captcha_url = "/accounts/" + image_url; |
+#endif |
+ |
+ *captcha_token = GetValueForKey("CaptchaToken", response); |
+ } |
+ return GR_UNAUTHORIZED; |
+ } |
+ |
+ if (status_code != talk_base::HC_OK) { |
+ return GR_ERROR; |
+ } |
+ |
+ *sid = GetValueForKey("SID", response); |
+ *lsid = GetValueForKey("LSID", response); |
+ if (auth) { |
+ *auth = GetValueForKey("Auth", response); |
+ } |
+ if (sid->empty() || lsid->empty()) { |
+ return GR_ERROR; |
+ } |
+ |
+ return GR_SUCCESS; |
+} |
+ |
+bool GaiaRequestAuthToken(talk_base::HttpClient* client, |
+ const std::string& sid, |
+ const std::string& lsid, |
+ const std::string& service, |
+ const GaiaServer& gaia_server) { |
+ std::string post_data; |
+ post_data += "SID=" + UrlEncodeString(sid); |
+ post_data += "&LSID=" + UrlEncodeString(lsid); |
+ post_data += "&service=" + service; |
+ post_data += "&Session=true"; // creates two week cookie |
+ |
+ client->reset(); |
+ client->set_server(talk_base::SocketAddress(gaia_server.hostname(), |
+ gaia_server.port(), false)); |
+ client->request().verb = talk_base::HV_POST; |
+ client->request().path = "/accounts/IssueAuthToken"; |
+ client->request().setContent("application/x-www-form-urlencoded", |
+ new talk_base::MemoryStream(post_data.data(), post_data.size())); |
+ client->response().document.reset(new talk_base::MemoryStream); |
+ client->start(); |
+ return true; |
+} |
+ |
+GaiaResponse GaiaParseAuthTokenResponse(const talk_base::HttpClient& client, |
+ std::string* auth_token) { |
+ if (client.response().scode != talk_base::HC_OK) { |
+ return GR_ERROR; |
+ } |
+ |
+ const talk_base::MemoryStream* stream = |
+ static_cast<const talk_base::MemoryStream*>( |
+ client.response().document.get()); |
+ size_t length; |
+ stream->GetPosition(&length); |
+ while ((length > 0) && isspace(stream->GetBuffer()[length-1])) |
+ --length; |
+ auth_token->assign(stream->GetBuffer(), length); |
+ return auth_token->empty() ? GR_ERROR : GR_SUCCESS; |
+} |
+ |
+} // namespace buzz |
Property changes on: chrome\browser\sync\notifier\gaia_auth\gaiahelper.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |