source: SMSSender/frontend/business/contactimporter/googlecontactimporter_base.cpp @ 378:7553d82ad234

separation-frontend-backend
Last change on this file since 378:7553d82ad234 was 378:7553d82ad234, checked in by Sämy Zehnder <saemy.zehnder@…>, 7 years ago
  • Reverts the removal of the CA certificates to avoid the disavailability of a service due to the system CA store not containing it's CA.
File size: 6.8 KB
Line 
1/*
2 smssender - A frontend for fast and easy SMS sending over different gateways.
3 Copyright (C) 2007-2014, gorrión. See http://smssender.gorrion.ch
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18#include "googlecontactimporter_base.h"
19
20#include <QRegExp>
21
22#include "common/domain/scontact.h"
23#include "common/domain/snumber.h"
24#include "common/exceptions/eexception.h"
25#include "common/network/snetworkreply.h"
26
27BaseGoogleContactImporter::BaseGoogleContactImporter(const BaseGoogleContactImporter::AuthData &authData)
28    : m_authData(authData)
29{
30    m_httpHelper.addTrustedCA(":/certs/Equifax_Secure_Certificate_Authority.crt");
31}
32
33void BaseGoogleContactImporter::importContacts(QSet<SContact *> *contacts) {
34    // TODO Use OAuth2
35    requestAuthToken();
36    m_httpHelper.defaultHeaders().insert("GData-Version", "3.0");
37
38    QString nextUrl = "http://www.google.com/m8/feeds/contacts/default/full?max-results=10000";
39    do {
40        QString contactsFeed =
41                QString::fromUtf8(m_httpHelper.syncGet(nextUrl)->readAll());
42        contactsFeed = SNetworkHelper::urldecodeString(contactsFeed);
43        parseContactsFeed(contactsFeed, contacts);
44
45        QRegExp rx("<link rel='next' type='application/atom\\+xml' href='([^']+)'/>");
46        if (rx.indexIn(contactsFeed) != -1) {
47            nextUrl = rx.cap(1);
48        } else {
49            break;
50        }
51    } while (true);
52}
53
54void BaseGoogleContactImporter::parseContactsFeed(const QString& feed, QSet<SContact *> *contacts) {
55    /*<entry gd:etag=""SXszeTVSLyt7ImA9WxFbFk8ORQU."">
56        <id>http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/base/59ea8d658e87e360</id>
57        <updated>2010-07-08T21:23:38.581Z</updated>
58        <app:edited>2010-07-08T21:23:38.581Z</app:edited>
59        <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
60        <title>test2</title>
61        <link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/%avoidwarninghere%*" href="http://www.google.com/m8/feeds/photos/media/saemy.zehnder%40gmail.com/59ea8d658e87e360" gd:etag=""VxFIFH0fSit7ImA0G0AqEU8PIQEjJkMyazA.""/>
62        <link rel="self" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
63        <link rel="edit" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
64        <gd:name>
65            <gd:fullName>test2</gd:fullName>
66            <gd:givenName>test2</gd:givenName>
67        </gd:name>
68        <gContact:nickname>nick1</gContact:nickname>
69        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 67</gd:phoneNumber>
70        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 68</gd:phoneNumber>
71        <gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/saemy.zehnder%40gmail.com/base/6"/>
72      </entry> */
73    QRegExp rx("<entry.*>(.*)</entry>");
74    rx.setMinimal(true);
75
76    int pos = 0;
77    while ((pos = rx.indexIn(feed, pos)) != -1) {
78        pos += rx.matchedLength();
79
80        try {
81            QString entry = rx.cap(1);
82
83            QRegExp rx2;
84            rx2.setMinimal(true);
85
86            rx2.setPattern("<gd:name>.*<gd:fullName>(.*)</gd:fullName>.*</gd:name>");
87            if (rx2.indexIn(entry) == -1) continue;
88            QString name = rx2.cap(1);
89
90            rx2.setPattern("<gd:phoneNumber rel='http://schemas.google.com/g/2005#mobile'.*>(.*)</gd:phoneNumber>");
91            if (rx2.indexIn(entry) == -1) continue;
92            SNumber number(rx2.cap(1));
93
94            if (!name.isEmpty() && number.isValid()) {
95                QScopedPointer<SContact> contact(new SContact);
96                contact->setName(name);
97                contact->setNumber(number);
98
99                rx2.setPattern("<gContact:nickname>(.*)</gContact:nickname>");
100                if ((rx2.indexIn(entry) != -1) && !rx2.cap(1).isEmpty()) {
101                    //qDebug() << rx2.cap(1);
102                    QStringList aliases;
103                    aliases.append(rx2.cap(1));
104                    contact->setAliases(aliases);
105                }
106
107#ifdef FRONTEND_GUI
108                rx2.setPattern("<link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/\\*' href='([^']+)' gd:etag='([^']+)'/>");
109                if (rx2.indexIn(entry) != -1) {
110                    QImage img = QImage::fromData(m_httpHelper.syncGet(rx2.cap(1))->readAll());
111                    if (!img.isNull()) {
112                        contact->setImage(img);
113                    }
114                }
115#endif
116
117                contacts->insert(contact.take());
118            }
119        } catch (...) {
120            // don't fail to import all contacts because of one...
121        }
122    }
123}
124
125void BaseGoogleContactImporter::requestAuthToken() {
126    QList<IParam*> posts;
127    posts.append(new SKeyValueParam("accountType", "GOOGLE"));
128    posts.append(new SKeyValueParam("Email", m_authData.username.toUtf8()));
129    posts.append(new SKeyValueParam("Passwd", m_authData.password.toUtf8()));
130    posts.append(new SKeyValueParam("service", "cp"));
131    posts.append(new SKeyValueParam("source", "gorrion-smssender-3"));
132
133    QString result;
134    try {
135        result = m_httpHelper.syncPost(QUrl::fromEncoded("https://www.google.com/accounts/ClientLogin"), posts)->readAll();
136    } catch (EException& e) {
137        result = "";
138    }
139
140    QRegExp rx("Auth=(\\S+)");
141    if (rx.indexIn(result) != -1) {
142        m_httpHelper.defaultHeaders().insert("Authorization", QString("GoogleLogin auth=" + rx.cap(1)).toUtf8());
143    } else {
144        EException("Login failed. You have probably entered incorrect userdata.")
145                .raise();
146    }
147}
148
149
150/********************************** BUILDER ***********************************/
151
152
153QString BaseGoogleContactImporter::Builder::description() const {
154    return QObject::tr("Import contacts from Google contacts.");
155}
156
157bool BaseGoogleContactImporter::Builder::isApplicable() const {
158    return true;
159}
160
161void BaseGoogleContactImporter::Builder::init() {
162    m_authData.username.clear();
163    m_authData.password.clear();
164}
165
166void BaseGoogleContactImporter::Builder::createImporters(
167        QSet<IContactImporter *> *importers) {
168    importers->insert(new BaseGoogleContactImporter(m_authData));
169}
Note: See TracBrowser for help on using the repository browser.