One more fix to connection handling.
[jenirok] / src / common / eniro.cpp
index b28760c..46fda30 100644 (file)
@@ -42,36 +42,28 @@ namespace
          "dk"
     };
 
-    static const QString INVALID_LOGIN_STRING = QObject::tr("Invalid login details");
-    static const QString TIMEOUT_STRING = QObject::tr("Request timed out");
+    static const QString INVALID_LOGIN_STRING = "Invalid login details";
+    static const QString TIMEOUT_STRING = "Request timed out";
     static const QString PERSON_REGEXP = "<td class=\"hTd2\">(.*)<b>(.*)</td>";
-    static const QString YELLOW_REGEXP = "<td class=\"hTd2\">(.*)<span class=\"gray\"\\}>(.*)</td>";
+    static const QString YELLOW_REGEXP = "<td class=\"hTd2\">(.*)<span class=\"gray\">(.*)</td>";
+    static const QString SINGLE_REGEXP = "<div class=\"header\">(.*)</div>(.*)<div class=\"callRow\">(.*)(<div class=\"block\">|</p>(.*)<br/>|</p>(.*)<br />)";
     static const QString NUMBER_REGEXP = "<div class=\"callRow\">(.*)</div>";
     static const QString LOGIN_CHECK = "<input class=\"inpTxt\" id=\"loginformUsername\"";
 }
 
-// Regexp used to remove numbers from string
-QRegExp Eniro::numberCleaner_ = QRegExp("([^0-9]+)");
-
-// Removes html tags from string
-QRegExp Eniro::tagStripper_ = QRegExp("<([^>]+)>");
-
-Eniro::Eniro(Site site, QObject *parent): QObject(parent), site_(site),
-username_(""), password_(""), loggedIn_(false), error_(NO_ERROR),
-errorString_(""), maxResults_(DEFAULT_MAX_RESULTS), timeout_(0), timerId_(0),
-findNumber_(true), pendingSearches_(), pendingNumberRequests_()
+Eniro::Eniro(QObject *parent): Source(parent), site_(Eniro::FI),
+loggedIn_(false), username_(""), password_(""),
+timerId_(0), pendingSearches_(), pendingNumberRequests_()
 {
-    connect(&http_, SIGNAL(requestFinished(int, bool)), this, SLOT(httpReady(int, bool)));
 }
 
 Eniro::~Eniro()
 {
-    abort();
 }
 
 void Eniro::abort()
 {
-    http_.abort();
+    Source::abort();
 
     for(searchMap::iterator sit = pendingSearches_.begin();
     sit != pendingSearches_.end(); sit++)
@@ -99,63 +91,32 @@ void Eniro::abort()
     pendingLoginRequests_.clear();
 }
 
-void Eniro::setMaxResults(unsigned int value)
-{
-    maxResults_ = value;
-}
-
-void Eniro::setFindNumber(bool value)
-{
-    findNumber_ = value;
-}
-
 void Eniro::setSite(Eniro::Site site)
 {
     site_ = site;
 }
 
-void Eniro::setTimeout(unsigned int ms)
+void Eniro::timerEvent(QTimerEvent* t)
 {
-    timeout_ = ms;
-    resetTimeout();
-}
+    Q_UNUSED(t);
 
-void Eniro::resetTimeout()
-{
-    if(timerId_)
-    {
-        killTimer(timerId_);
-    }
-    if(timeout_)
-    {
-        timerId_ = startTimer(timeout_);
-    }
-}
+    int currentId = http_.currentId();
 
-void Eniro::timerEvent(QTimerEvent* t)
-{
-    if(t->timerId() == timerId_)
+    if(currentId)
     {
-        int currentId = http_.currentId();
+        searchMap::const_iterator it = pendingSearches_.find(currentId);
 
-        if(currentId)
+        if(it != pendingSearches_.end())
         {
-            searchMap::const_iterator it = pendingSearches_.find(currentId);
-
-            if(it != pendingSearches_.end())
-            {
-                QVector <Eniro::Result> results = it.value()->results;
-                SearchDetails details = it.value()->details;
+            QVector <Eniro::Result> results = it.value()->results;
+            SearchDetails details = it.value()->details;
 
-                abort();
+            abort();
 
-                error_ = TIMEOUT;
-                errorString_ = TIMEOUT_STRING;
+            setError(TIMEOUT, TIMEOUT_STRING);
 
-                emit requestFinished(results, details, true);
-            }
+            emit requestFinished(results, details, true);
         }
-
     }
 }
 
@@ -174,25 +135,14 @@ void Eniro::logout()
     loggedIn_ = false;
 }
 
-void Eniro::testLogin()
-{
-    QUrl url = createUrl("", "");
-
-    url.addQueryItem("what", "mobwp");
-    http_.setHost(url.host(), url.port(80));
-    int id = http_.get(url.encodedPath() + '?' + url.encodedQuery());
-
-    pendingLoginRequests_.insert(id);
-}
-
-bool Eniro::search(SearchDetails const& details)
+void Eniro::search(SearchDetails const& details)
 {
     resetTimeout();
 
     SearchType type = details.type;
 
     // Only logged in users can use other than person search
-    if(!loggedIn_)
+    if(!loggedIn_ && site_ == FI)
     {
         type = PERSONS;
     }
@@ -200,7 +150,7 @@ bool Eniro::search(SearchDetails const& details)
     QUrl url = createUrl(details.query, details.location);
     QString what;
 
-    if(loggedIn_)
+    if(loggedIn_ || site_ != FI)
     {
         switch(type)
         {
@@ -214,6 +164,7 @@ bool Eniro::search(SearchDetails const& details)
 
         default:
             what = "moball";
+            break;
         }
 
     }
@@ -227,7 +178,7 @@ bool Eniro::search(SearchDetails const& details)
     http_.setHost(url.host(), url.port(80));
     int id = http_.get(url.encodedPath() + '?' + url.encodedQuery());
 
-    QVector <Result> results;
+    QVector <Source::Result> results;
 
     // Store search data for later identification
     SearchData* newData = new SearchData;
@@ -239,26 +190,10 @@ bool Eniro::search(SearchDetails const& details)
     // Store request id so that it can be identified later
     pendingSearches_[id] = newData;
 
-    return true;
 }
 
-Eniro::Error Eniro::error() const
+void Eniro::handleHttpData(int id, QByteArray const& data)
 {
-    return error_;
-}
-
-const QString& Eniro::errorString() const
-{
-    return errorString_;
-}
-
-void Eniro::httpReady(int id, bool error)
-{
-    if(error)
-    {
-        qDebug() << "Error: " << http_.errorString();
-    }
-
     searchMap::const_iterator searchIt;
     numberMap::const_iterator numberIt;
 
@@ -266,37 +201,16 @@ void Eniro::httpReady(int id, bool error)
     if((searchIt = pendingSearches_.find(id)) !=
         pendingSearches_.end())
     {
-        if(error)
-        {
-            error_ = CONNECTION_FAILURE;
-            errorString_ = http_.errorString();
-            emitRequestFinished(id, searchIt.value(), true);
-            return;
-        }
-
-        QString result(http_.readAll());
-
         // Load results from html data
-        loadResults(id, result);
+        loadResults(id, data);
     }
 
     // Check if request is pending number requests
     else if((numberIt = pendingNumberRequests_.find(id)) !=
         pendingNumberRequests_.end())
     {
-        if(error)
-        {
-            error_ = CONNECTION_FAILURE;
-            errorString_ = http_.errorString();
-            delete pendingNumberRequests_[id];
-            pendingNumberRequests_.remove(id);
-            return;
-        }
-
-        QString result(http_.readAll());
-
         // Load number from html data
-        loadNumber(id, result);
+        loadNumber(id, data);
     }
 
     // Check for login request
@@ -305,17 +219,8 @@ void Eniro::httpReady(int id, bool error)
     {
         bool success = true;
 
-        if(!error)
-        {
-            QString result(http_.readAll());
-
-            // If html source contains LOGIN_CHECK, login failed
-            if(result.indexOf(LOGIN_CHECK) != -1)
-            {
-                success = false;
-            }
-        }
-        else
+        // If html source contains LOGIN_CHECK, login failed
+        if(data.indexOf(LOGIN_CHECK) != -1)
         {
             success = false;
         }
@@ -325,25 +230,42 @@ void Eniro::httpReady(int id, bool error)
 
 }
 
-// Loads results from html source code
-void Eniro::loadResults(int id, QString const& httpData)
+void Eniro::handleHttpError(int id)
 {
-    searchMap::iterator it = pendingSearches_.find(id);
-    QString expr;
+    searchMap::const_iterator searchIt;
+    numberMap::const_iterator numberIt;
 
-    switch(it.value()->details.type)
+    // Check if request is pending search request
+    if((searchIt = pendingSearches_.find(id)) !=
+        pendingSearches_.end())
     {
-    case YELLOW_PAGES:
-        expr = YELLOW_REGEXP;
-        break;
-    case PERSONS:
-        expr = PERSON_REGEXP;
-        break;
-    default:
-        return;
+        setError(CONNECTION_FAILURE, http_.errorString());
+        emitRequestFinished(id, searchIt.value(), true);
     }
 
-    QRegExp rx(expr);
+    // Check if request is pending number requests
+    else if((numberIt = pendingNumberRequests_.find(id)) !=
+        pendingNumberRequests_.end())
+    {
+        setError(CONNECTION_FAILURE, http_.errorString());
+        delete pendingNumberRequests_[id];
+        pendingNumberRequests_.remove(id);
+    }
+
+    // Check for login request
+    else if(pendingLoginRequests_.find(id) !=
+        pendingLoginRequests_.end())
+    {
+        emit loginStatus(false);
+    }
+}
+
+// Loads results from html source code
+void Eniro::loadResults(int id, QString const& httpData)
+{
+    searchMap::iterator it = pendingSearches_.find(id);
+
+    QRegExp rx("((" + YELLOW_REGEXP + ")|(" + PERSON_REGEXP + ")|(" + SINGLE_REGEXP + "))");
     rx.setMinimal(true);
 
     bool requestsPending = false;
@@ -355,8 +277,10 @@ void Eniro::loadResults(int id, QString const& httpData)
     {
         pos += rx.matchedLength();
 
-        data = rx.cap(2);
+        data = rx.cap(1);
+
         data = stripTags(data);
+
         QStringList rows = data.split('\n');
 
         for(int i = 0; i < rows.size(); i++)
@@ -379,6 +303,19 @@ void Eniro::loadResults(int id, QString const& httpData)
 
         Result result;
 
+        switch(site_)
+        {
+        case FI:
+            result.country = "Finland";
+            break;
+        case SE:
+            result.country = "Sweden";
+            break;
+        case DK:
+            result.country = "Denmark";
+            break;
+        }
+
         int size = rows.size();
 
         switch(size)
@@ -393,9 +330,18 @@ void Eniro::loadResults(int id, QString const& httpData)
             break;
 
         case 3:
-            result.name = rows[0];
-            result.street = rows[1];
-            result.city = rows[2];
+            if(isPhoneNumber(rows[1]))
+            {
+                result.name = rows[0];
+                result.number = cleanUpNumber(rows[1]);
+                result.city = rows[2];
+            }
+            else
+            {
+                result.name = rows[0];
+                result.street = rows[1];
+                result.city = rows[2];
+            }
             break;
 
         case 4:
@@ -407,6 +353,35 @@ void Eniro::loadResults(int id, QString const& httpData)
             break;
 
         default:
+            bool ok = false;
+
+            for(int a = 0; a < size && a < 8; a++)
+            {
+                if(isPhoneNumber(rows[a]))
+                {
+                    result.name = rows[0];
+                    result.number = cleanUpNumber(rows[a]);
+
+                    for(int i = a + 1; i < size && i < 8; i++)
+                    {
+                        if(!isPhoneNumber(rows[i]) && size > i + 1 && isStreet(rows[i]))
+                        {
+                            result.street = rows[i];
+                            result.city = rows[i+1];
+                            ok = true;
+                            break;
+                        }
+                    }
+
+                }
+
+            }
+
+            if(ok)
+            {
+                break;
+            }
+
             continue;
 
         }
@@ -415,9 +390,9 @@ void Eniro::loadResults(int id, QString const& httpData)
 
         unsigned int foundResults = ++(it.value()->numbersTotal);
 
-        // If phone number searh is enabled, we have to make another
+        // If phone number search is enabled, we have to make another
         // request to find it out
-        if(findNumber_ && size < 4 && loggedIn_ &&
+        if(getFindNumber() && size < 4 && (loggedIn_ || site_ != FI) &&
                 it.value()->details.type != YELLOW_PAGES)
         {
             requestsPending = true;
@@ -429,8 +404,10 @@ void Eniro::loadResults(int id, QString const& httpData)
             emit resultAvailable(result, it.value()->details);
         }
 
+        unsigned int maxResults = getMaxResults();
+
         // Stop searching if max results is reached
-        if(maxResults_ && (foundResults >= maxResults_))
+        if(maxResults && (foundResults >= maxResults))
         {
             break;
         }
@@ -444,8 +421,7 @@ void Eniro::loadResults(int id, QString const& httpData)
 
         if(httpData.indexOf(LOGIN_CHECK) != -1)
         {
-            error_ = INVALID_LOGIN;
-            errorString_ = INVALID_LOGIN_STRING;
+            setError(INVALID_LOGIN, INVALID_LOGIN_STRING),
             error = true;
         }
 
@@ -506,8 +482,7 @@ void Eniro::loadNumber(int id, QString const& result)
 
     if(error)
     {
-        error_ = INVALID_LOGIN;
-        errorString_ = INVALID_LOGIN;
+        setError(INVALID_LOGIN, INVALID_LOGIN_STRING);
         emitRequestFinished(searchIt.key(), searchIt.value(), true);
     }
 
@@ -534,18 +509,19 @@ QUrl Eniro::createUrl(QString const& query, QString const& location)
         url.addQueryItem("geo_area", location);
     }
 
-    if(maxResults_)
+    unsigned int maxResults = getMaxResults();
+
+    if(maxResults)
     {
-        url.addQueryItem("hpp", QString::number(maxResults_));
+        url.addQueryItem("hpp", QString::number(maxResults));
     }
-    if(loggedIn_)
+    if(loggedIn_ && site_ == FI)
     {
         url.addQueryItem("login_name", username_);
         url.addQueryItem("login_password", password_);
     }
 
-    QByteArray path = url.encodedQuery().replace('+', "%2B");
-    url.setEncodedQuery(path);
+    fixUrl(url);
 
     return url;
 }
@@ -568,49 +544,16 @@ void Eniro::getNumberForResult(int id, int index, SearchDetails const& details)
 
 void Eniro::emitRequestFinished(int key, SearchData* data, bool error)
 {
-
-    // Do not emit "Request aborted" error
-    if(!(error && (http_.error() == QHttp::Aborted)))
-    {
-        emit requestFinished(data->results, data->details, error);
-    }
-
+    emit requestFinished(data->results, data->details, error);
     delete pendingSearches_[key];
     pendingSearches_[key] = 0;
     pendingSearches_.remove(key);
 }
 
-QString Eniro::ucFirst(QString& str)
-{
-    if (str.size() < 1) {
-        return "";
-    }
-
-    QStringList tokens = str.split(" ");
-    QList<QString>::iterator tokItr;
-
-    for (tokItr = tokens.begin(); tokItr != tokens.end(); ++tokItr)
-    {
-        (*tokItr) = (*tokItr).at(0).toUpper() + (*tokItr).mid(1);
-    }
-
-    return tokens.join(" ");
-}
-
-QString& Eniro::cleanUpNumber(QString& number)
-{
-    return number.replace(numberCleaner_, "");
-}
-
-QString& Eniro::stripTags(QString& string)
-{
-    return string.replace(tagStripper_, "");
-}
 
 QMap <Eniro::Site, Eniro::SiteDetails> Eniro::getSites()
 {
     QMap <Site, SiteDetails> sites;
-    SiteDetails details;
 
     for(int i = 0; i < SITE_COUNT; i++)
     {
@@ -633,17 +576,23 @@ Eniro::Site Eniro::stringToSite(QString const& str)
         if(lower == SITE_NAMES[i] || lower == SITE_IDS[i])
         {
             site = static_cast <Site> (i);
+            break;
         }
     }
 
     return site;
 }
 
-Eniro::SearchDetails::SearchDetails(QString const& q,
-                                    QString const& loc,
-                                    SearchType t)
+bool Eniro::isStreet(QString const& str)
 {
-    query = q;
-    location = loc;
-    type = t;
+    static QRegExp number("([0-9]+)");
+    int a = number.indexIn(str);
+    int b = str.indexOf(" ");
+
+    if((a == -1 && b == -1) || (a != -1 && b != -1))
+    {
+        return true;
+    }
+
+    return false;
 }