source: SMSSender/frontend/business/contactimporter/abstractgooglecontactimporter.cpp @ 315:e6c8bb244ecd

separation-frontend-backend
Last change on this file since 315:e6c8bb244ecd was 315:e6c8bb244ecd, checked in by Sämy Zehnder <saemy.zehnder@…>, 6 years ago
  • Separates the frontend from the backend code.
  • At this point the schoolnet gateway is converted only.
  • Removes bc & da prefixes from the filenames.
File size: 6.8 KB
Line 
1/*
2 smssender - A frontend for fast and easy SMS sending over different gateways.
3 Copyright (C) 2007-2012, 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 "abstractgooglecontactimporter.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
27AbstractGoogleContactImporter::AbstractGoogleContactImporter(SNetworkHelper *httpHelper)
28    : m_httpHelper(httpHelper)
29{
30    m_httpHelper->addTrustedCA(":/certs/VerisignClass3PublicPrimaryCertificationAuthority.crt");
31}
32
33QString AbstractGoogleContactImporter::describingName() const {
34    return QObject::tr("Import contacts from google contacts.");
35}
36
37bool AbstractGoogleContactImporter::isApplicable() const {
38    return true;
39}
40
41
42void AbstractGoogleContactImporter::init() {
43}
44
45/*QList<IContactImporter::Page> AbstractGoogleContactImporter::preImportPages() {
46    m_authPage.reset(createAuthPage());
47
48    QList<IContactImporter::Page> pages;
49    pages.append(m_authPage.data());
50    return pages;
51}*/
52
53QSet<SContact*> AbstractGoogleContactImporter::importContacts() {
54    QSet<SContact*> contacts;
55
56    // TODO Use OAuth2
57    requestAuthToken();
58    m_httpHelper->defaultHeaders().insert("GData-Version", "3.0");
59
60    QString nextUrl = "http://www.google.com/m8/feeds/contacts/default/thin?max-results=10000";
61    do {
62        QString contactsFeed = m_httpHelper->syncGet(nextUrl)->readAll();
63        contactsFeed = SNetworkHelper::urldecodeString(contactsFeed);
64        parseContactsFeed(contactsFeed, &contacts);
65
66        QRegExp rx("<link rel='next' type='application/atom\\+xml' href='([^']+)'/>");
67        if (rx.indexIn(contactsFeed) != -1) {
68            nextUrl = rx.cap(1);
69        } else {
70            break;
71        }
72    } while (true);
73
74    return contacts;
75}
76
77void AbstractGoogleContactImporter::parseContactsFeed(const QString& feed, QSet<SContact *> *contacts) {
78    /*<entry gd:etag=""SXszeTVSLyt7ImA9WxFbFk8ORQU."">
79        <id>http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/base/59ea8d658e87e360</id>
80        <updated>2010-07-08T21:23:38.581Z</updated>
81        <app:edited>2010-07-08T21:23:38.581Z</app:edited>
82        <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
83        <title>test2</title>
84        <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.""/>
85        <link rel="self" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
86        <link rel="edit" type="application/atom+xml" href="http://www.google.com/m8/feeds/contacts/saemy.zehnder%40gmail.com/thin/59ea8d658e87e360"/>
87        <gd:name>
88            <gd:fullName>test2</gd:fullName>
89            <gd:givenName>test2</gd:givenName>
90        </gd:name>
91        <gContact:nickname>nick1</gContact:nickname>
92        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 67</gd:phoneNumber>
93        <gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">+41 079 12345 68</gd:phoneNumber>
94        <gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/saemy.zehnder%40gmail.com/base/6"/>
95      </entry> */
96    QRegExp rx("<entry.*>(.*)</entry>");
97    rx.setMinimal(true);
98
99    int pos = 0;
100    while ((pos = rx.indexIn(feed, pos)) != -1) {
101        pos += rx.matchedLength();
102
103        try {
104            QString entry = rx.cap(1);
105
106            QRegExp rx2;
107            rx2.setMinimal(true);
108
109            rx2.setPattern("<gd:name>.*<gd:givenName>(.*)</gd:givenName>.*</gd:name>");
110            if (rx2.indexIn(entry) == -1) continue;
111            QString name = rx2.cap(1);
112
113            rx2.setPattern("<gd:phoneNumber rel='http://schemas.google.com/g/2005#mobile'>(.*)</gd:phoneNumber>");
114            if (rx2.indexIn(entry) == -1) continue;
115            SNumber number(rx2.cap(1));
116
117            if (!name.isEmpty() && number.isValid()) {
118                QScopedPointer<SContact> contact(new SContact);
119                contact->setName(name);
120                contact->setNumber(number);
121
122                rx2.setPattern("<gContact:nickname>(.*)</gContact:nickname>");
123                if ((rx2.indexIn(entry) != -1) && !rx2.cap(1).isEmpty()) {
124                    //qDebug() << rx2.cap(1);
125                    QStringList aliases;
126                    aliases.append(rx2.cap(1));
127                    contact->setAliases(aliases);
128                }
129
130#ifdef FRONTEND_GUI
131                rx2.setPattern("<link rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/\\*' href='([^']+)' gd:etag='([^']+)'/>");
132                if (rx2.indexIn(entry) != -1) {
133                    QImage img = QImage::fromData(m_httpHelper->syncGet(rx2.cap(1))->readAll());
134                    if (!img.isNull()) {
135                        contact->setImage(img);
136                    }
137                }
138#endif
139
140                contacts->insert(contact.take());
141            }
142        } catch (...) {
143            // don't fail to import all contacts because of one...
144        }
145    }
146}
147
148void AbstractGoogleContactImporter::requestAuthToken() {
149    const AuthData &authData = getAuthData();
150
151    QList<IParam*> posts;
152    posts.append(new SKeyValueParam("accountType", "GOOGLE"));
153    posts.append(new SKeyValueParam("Email",       authData.m_username.toUtf8()));
154    posts.append(new SKeyValueParam("Passwd",      authData.m_password.toUtf8()));
155    posts.append(new SKeyValueParam("service",     "cp"));
156    posts.append(new SKeyValueParam("source",      "gorrion-smssender-3"));
157
158    QString result;
159    try {
160        result = m_httpHelper->syncPost(QUrl::fromEncoded("https://www.google.com/accounts/ClientLogin"), posts)->readAll();
161    } catch (EException& e) {
162        result = "";
163    }
164
165    QRegExp rx("Auth=(\\S+)");
166    if (rx.indexIn(result) != -1) {
167        m_httpHelper->defaultHeaders().insert("Authorization", QString("GoogleLogin auth=" + rx.cap(1)).toUtf8());
168    } else {
169        EException("Login failed. You have probably entered incorrect userdata.")
170                .raise();
171    }
172}
Note: See TracBrowser for help on using the repository browser.