source: SMSSender/frontend/business/contactimporter/googlecontactimporter_base.cpp @ 405:f056fa7fe8b4

Last change on this file since 405:f056fa7fe8b4 was 405:f056fa7fe8b4, checked in by Sämy Zehnder <saemy.zehnder@…>, 6 years ago
  • Switches to OAuth2 authentication for importing contacts from Google.
File size: 6.0 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#include "frontend/business/contactimporter/googlecontactimporter.h"
27
28BaseGoogleContactImporter::BaseGoogleContactImporter(
29        const OAuth2::AccessToken &accessToken)
30    : m_accessToken(accessToken)
31{
32    m_httpHelper.addTrustedCA(":/certs/Equifax_Secure_Certificate_Authority.crt");
33}
34
35void BaseGoogleContactImporter::importContacts(QSet<SContact *> *contacts) {
36    m_httpHelper.defaultHeaders().insert(
37                "Authorization",
38                QString("%1 %2")
39                    .arg(m_accessToken.tokenType)
40                    .arg(m_accessToken.accessToken)
41                    .toUtf8());
42    m_httpHelper.defaultHeaders().insert("GData-Version", "3.0");
43
44    QString nextUrl = "http://www.google.com/m8/feeds/contacts/default/full?max-results=10000";
45    do {
46        QString contactsFeed =
47                QString::fromUtf8(m_httpHelper.syncGet(nextUrl)->readAll());
48        contactsFeed = SNetworkHelper::urldecodeString(contactsFeed);
49        parseContactsFeed(contactsFeed, contacts);
50
51        QRegExp rx("<link rel='next' type='application/atom\\+xml' href='([^']+)'/>");
52        if (rx.indexIn(contactsFeed) != -1) {
53            nextUrl = rx.cap(1);
54        } else {
55            break;
56        }
57    } while (true);
58}
59
60void BaseGoogleContactImporter::parseContactsFeed(const QString &feed, QSet<SContact *> *contacts) {
61    /*<entry gd:etag=""SXszeTVSLyt7ImA9WxFbFk8ORQU."">
62        <id>http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/base/59ea8d658e87e360</id>
63        <updated>2010-07-08T21:23:38.581Z</updated>
64        <app:edited>2010-07-08T21:23:38.581Z</app:edited>
65        <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
66        <title>test2</title>
67        <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.""/>
68        <link rel="self" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
69        <link rel="edit" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
70        <gd:name>
71            <gd:fullName>test2</gd:fullName>
72            <gd:givenName>test2</gd:givenName>
73        </gd:name>
74        <gContact:nickname>nick1</gContact:nickname>
75        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 67</gd:phoneNumber>
76        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 68</gd:phoneNumber>
77        <gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/saemy.zehnder%40gmail.com/base/6"/>
78      </entry> */
79    QRegExp rx("<entry.*>(.*)</entry>");
80    rx.setMinimal(true);
81
82    int pos = 0;
83    while ((pos = rx.indexIn(feed, pos)) != -1) {
84        pos += rx.matchedLength();
85
86        try {
87            QString entry = rx.cap(1);
88
89            QRegExp rx2;
90            rx2.setMinimal(true);
91
92            rx2.setPattern("<gd:name>.*<gd:fullName>(.*)</gd:fullName>.*</gd:name>");
93            if (rx2.indexIn(entry) == -1) continue;
94            QString name = rx2.cap(1);
95
96            rx2.setPattern("<gd:phoneNumber rel='http://schemas.google.com/g/2005#mobile'.*>(.*)</gd:phoneNumber>");
97            if (rx2.indexIn(entry) == -1) continue;
98            SNumber number(rx2.cap(1));
99
100            if (!name.isEmpty() && number.isValid()) {
101                QScopedPointer<SContact> contact(new SContact);
102                contact->setName(name);
103                contact->setNumber(number);
104
105                parseEntry(entry, contact.data());
106
107                contacts->insert(contact.take());
108            }
109        } catch (EException &e) {
110            // don't fail to import all contacts because of one...
111            qWarning() << "Failed to import contact: " << e.chainedWhat();
112        } catch (...) {
113            qWarning() << "Failed to import contact: Unknown reason.";
114        }
115    }
116}
117
118void BaseGoogleContactImporter::parseEntry(const QString &entry, SContact *contact) {
119    QRegExp rx("<gContact:nickname>(.*)</gContact:nickname>");
120    rx.setMinimal(true);
121
122    if ((rx.indexIn(entry) != -1) && !rx.cap(1).isEmpty()) {
123        QStringList aliases;
124        aliases.append(rx.cap(1));
125        contact->setAliases(aliases);
126    }
127
128}
129
130SNetworkHelper *BaseGoogleContactImporter::httpHelper() {
131    return &m_httpHelper;
132}
133
134
135/********************************** BUILDER ***********************************/
136
137
138QString BaseGoogleContactImporter::Builder::description() const {
139    return QObject::tr("Import contacts from Google contacts.");
140}
141
142bool BaseGoogleContactImporter::Builder::isApplicable() const {
143    return true;
144}
145
146void BaseGoogleContactImporter::Builder::init() {
147    m_accessToken = OAuth2::AccessToken();
148}
149
150void BaseGoogleContactImporter::Builder::createImporters(
151        QSet<IContactImporter *> *importers) {
152    importers->insert(new GoogleContactImporter(m_accessToken));
153}
Note: See TracBrowser for help on using the repository browser.