1 /*
2     SPDX-FileCopyrightText: 2002 Rik Hemsley (rikkus) <rik@kde.org>
3     SPDX-FileCopyrightText: 2002 Benjamin Meyer <ben-devel@meyerhome.net>
4     SPDX-FileCopyrightText: 2005 Richard Lärkäng <nouseforaname@home.se>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "synccddbplookup.h"
10 #include "logging.h"
11 
12 #include <QStringList>
13 
14 namespace KCDDB
15 {
SyncCDDBPLookup()16   SyncCDDBPLookup::SyncCDDBPLookup()
17     : CDDBPLookup()
18   {
19   }
20 
~SyncCDDBPLookup()21   SyncCDDBPLookup::~SyncCDDBPLookup()
22   {
23     // Empty.
24   }
25 
26     Result
lookup(const QString & hostName,uint port,const TrackOffsetList & trackOffsetList)27   SyncCDDBPLookup::lookup
28   (
29     const QString         & hostName,
30     uint                    port,
31     const TrackOffsetList & trackOffsetList
32   )
33   {
34     trackOffsetList_ = trackOffsetList;
35 
36     socket_ = new QTcpSocket;
37     socket_->connectToHost(hostName, port);
38 
39     if ( !socket_->waitForConnected(30000) )
40     {
41       qCDebug(LIBKCDDB) << "Couldn't connect to " << socket_->peerName() << ":" << socket_->peerPort();
42       qCDebug(LIBKCDDB) << "Socket error: " << socket_->errorString();
43       const auto socketError = socket_->error();
44       if ( socketError == QAbstractSocket::HostNotFoundError )
45         return HostNotFound;
46       else if ( socketError == QAbstractSocket::SocketTimeoutError )
47         return NoResponse;
48       else
49         return UnknownError;
50     }
51 
52     Result result;
53 
54     // Try a handshake.
55     result = shakeHands();
56     if ( Success != result )
57       return result;
58 
59     // Run a query.
60     result = runQuery();
61     if ( Success != result )
62       return result;
63 
64     if (matchList_.isEmpty())
65       return NoRecordFound;
66 
67 	qCDebug(LIBKCDDB) << matchList_.count() << " matches found.";
68 
69     // For each match, read the cd info from the server and save it to
70     // cdInfoList.
71     CDDBMatchList::ConstIterator matchIt = matchList_.constBegin();
72 
73     while ( matchIt != matchList_.constEnd() )
74     {
75       CDDBMatch match( *matchIt );
76       result = matchToCDInfo( match );
77       ++matchIt;
78     }
79 
80     sendQuit();
81 
82     close();
83 
84     return Success;
85   }
86 
87     Result
shakeHands()88   SyncCDDBPLookup::shakeHands()
89   {
90     QString line = readLine();
91 
92     if ( !parseGreeting( line ) )
93       return ServerError;
94 
95     sendHandshake();
96 
97     line = readLine();
98 
99     if ( !parseHandshake( line ) )
100       return ServerError;
101 
102     sendProto();
103 
104     // Ignore the response for now
105     readLine();
106 
107     return Success;
108   }
109 
110     Result
runQuery()111   SyncCDDBPLookup::runQuery()
112   {
113     Result result;
114 
115     sendQuery();
116 
117     QString line = readLine();
118     result = parseQuery( line );
119 
120     if ( ServerError == result )
121       return ServerError;
122 
123     if ( MultipleRecordFound == result )
124     {
125       // We have multiple matches
126       line = readLine();
127 
128       while (!line.startsWith(QLatin1String( "." )) && !line.isNull() )
129       {
130         parseExtraMatch( line );
131         line = readLine();
132       }
133     }
134 
135     return Success;
136   }
137 
138     Result
matchToCDInfo(const CDDBMatch & match)139   SyncCDDBPLookup::matchToCDInfo( const CDDBMatch & match )
140   {
141     sendRead( match );
142 
143     QString line = readLine();
144 
145     Result result = parseRead( line );
146     if ( Success != result )
147       return result;
148 
149     QStringList lineList;
150     line = readLine();
151 
152     while ( !line.startsWith(QLatin1String( "." )) && !line.isNull() )
153     {
154       lineList.append( line );
155       line = readLine();
156     }
157 
158     CDInfo info;
159 
160     if ( info.load( lineList ) )
161     {
162       info.set( QLatin1String( "category" ), category_ );
163       info.set( QLatin1String( "discid" ), discid_ );
164       info.set( QLatin1String( "source" ), QLatin1String( "freedb" ) );
165       cdInfoList_.append( info );
166     }
167 
168     return Success;
169   }
170 
171     QString
readLine()172   SyncCDDBPLookup::readLine()
173   {
174     if ( !isConnected() )
175     {
176 	  qCDebug(LIBKCDDB) << "socket status: " << socket_->state();
177       return QString();
178     }
179 
180     if (!socket_->canReadLine())
181     {
182       if (!socket_->waitForReadyRead(-1))
183         return QString();
184     }
185 
186     return QString::fromUtf8(socket_->readLine());
187   }
188 }
189 
190 // vim:tabstop=2:shiftwidth=2:expandtab:cinoptions=(s,U1,m1
191