Merge lp:~dobey/ubuntuone-credentials/server-timestamp into lp:ubuntuone-credentials
- server-timestamp
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 228 |
Merged at revision: | 222 |
Proposed branch: | lp:~dobey/ubuntuone-credentials/server-timestamp |
Merge into: | lp:ubuntuone-credentials |
Diff against target: |
503 lines (+292/-11) 9 files modified
.bzrignore (+1/-0) debian/libubuntuoneauth-2.0-0.symbols (+2/-0) libubuntuoneauth/tests/CMakeLists.txt (+5/-0) libubuntuoneauth/tests/main.cpp (+4/-2) libubuntuoneauth/tests/mock_sso_server.py.in (+57/-0) libubuntuoneauth/tests/test_token.cpp (+103/-2) libubuntuoneauth/tests/test_token.h (+14/-1) libubuntuoneauth/token.cpp (+102/-5) libubuntuoneauth/token.h (+4/-1) |
To merge this branch: | bzr merge lp:~dobey/ubuntuone-credentials/server-timestamp |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Abstain | ||
Charles Kerr (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+279173@code.launchpad.net |
Commit message
Retrieve current timestamp from server to use in OAuth signatures.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:220
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:221
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:222
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:223
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:224
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:225
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:226
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alejandro J. Cura (alecu) wrote : | # |
Please put lines 387-395 in a separate function, and add unit tests for it with the following cases:
- server time is much later than client
- server time is much earlier than client
Even better: make a new class so _ts_check and _ts_skew are member objects and can be accessed easily by tests, and make signUrl have a static instance of that new class.
Please ping me if you need further reviews during my time off.
Alejandro J. Cura (alecu) wrote : | # |
Correction: I meant lines 381-395.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:227
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:228
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Looks good.
The one nitpick I have is approving while alecu is on leave, since the branch doesn't expose -ts_check and _ts_skew as requested by him. But he expressed it as a stretch goal, and after talking with dobey about it in irc I think this version is fine.
Alejandro J. Cura (alecu) wrote : | # |
I'm not finding the time to do a proper review, but I see that the changes I requested have been made, so I'm changing my review to Abstain.
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2014-01-15 19:35:23 +0000 |
3 | +++ .bzrignore 2015-12-07 21:37:17 +0000 |
4 | @@ -8,6 +8,7 @@ |
5 | signing-example |
6 | test-ubuntuoneauth |
7 | moc_*.cpp |
8 | +mock_sso_server.py |
9 | qmldir |
10 | ui_*.h |
11 | *_automoc.cpp |
12 | |
13 | === modified file 'debian/libubuntuoneauth-2.0-0.symbols' |
14 | --- debian/libubuntuoneauth-2.0-0.symbols 2015-06-17 16:58:41 +0000 |
15 | +++ debian/libubuntuoneauth-2.0-0.symbols 2015-12-07 21:37:17 +0000 |
16 | @@ -114,6 +114,8 @@ |
17 | (c++)"UbuntuOne::Token::consumerKey() const@Base" 15.10+15.10.20150617 |
18 | (c++)"UbuntuOne::Token::created() const@Base" 14.04+14.10.20140818 |
19 | (c++)"UbuntuOne::Token::updated() const@Base" 14.04+14.10.20140818 |
20 | + (c++)"UbuntuOne::Token::getServerTimestamp() const@Base" 0replaceme |
21 | + (c++)"UbuntuOne::Token::addOAuthTimestamp(QString) const@Base" 0replaceme |
22 | (c++)"UbuntuOne::Keyring::storeToken(UbuntuOne::Token)@Base" 13.08 |
23 | (c++)"UbuntuOne::Keyring::storeToken(UbuntuOne::Token, QString const&)@Base" 14.04+14.10.20140802 |
24 | (c++)"UbuntuOne::Keyring::tokenFound(UbuntuOne::Token const&)@Base" 13.08 |
25 | |
26 | === modified file 'libubuntuoneauth/tests/CMakeLists.txt' |
27 | --- libubuntuoneauth/tests/CMakeLists.txt 2013-06-14 22:30:19 +0000 |
28 | +++ libubuntuoneauth/tests/CMakeLists.txt 2015-12-07 21:37:17 +0000 |
29 | @@ -16,6 +16,11 @@ |
30 | -L${CMAKE_BINARY_DIR}/libubuntuoneauth |
31 | ${AUTH_LIB_NAME}) |
32 | |
33 | +configure_file( |
34 | + mock_sso_server.py.in |
35 | + mock_sso_server.py |
36 | +) |
37 | + |
38 | add_custom_target(ubuntuoneauth-tests |
39 | COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TESTS_TARGET} |
40 | DEPENDS ${TESTS_TARGET} |
41 | |
42 | === modified file 'libubuntuoneauth/tests/main.cpp' |
43 | --- libubuntuoneauth/tests/main.cpp 2013-06-14 22:30:19 +0000 |
44 | +++ libubuntuoneauth/tests/main.cpp 2015-12-07 21:37:17 +0000 |
45 | @@ -1,5 +1,5 @@ |
46 | /* |
47 | - * Copyright 2013 Canonical Ltd. |
48 | + * Copyright 2013-2015 Canonical Ltd. |
49 | * |
50 | * This library is free software; you can redistribute it and/or |
51 | * modify it under the terms of version 3 of the GNU Lesser General Public |
52 | @@ -24,7 +24,7 @@ |
53 | #include "test_requests.h" |
54 | #include "test_responses.h" |
55 | |
56 | -int main() |
57 | +int main(int argc, char** argv) |
58 | { |
59 | QByteArray fake_home = QDir::currentPath().toUtf8() + "/_test_temp"; |
60 | /* Need to alter some environment variables to avoid contamination. */ |
61 | @@ -40,6 +40,8 @@ |
62 | |
63 | /* Token tests */ |
64 | TestToken test_token; |
65 | + test_token.argc = argc; |
66 | + test_token.argv = argv; |
67 | |
68 | /* Request tests */ |
69 | TestOAuthTokenRequests test_oauth_token_requests; |
70 | |
71 | === added file 'libubuntuoneauth/tests/mock_sso_server.py.in' |
72 | --- libubuntuoneauth/tests/mock_sso_server.py.in 1970-01-01 00:00:00 +0000 |
73 | +++ libubuntuoneauth/tests/mock_sso_server.py.in 2015-12-07 21:37:17 +0000 |
74 | @@ -0,0 +1,57 @@ |
75 | +#!/usr/bin/python3 |
76 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
77 | +# |
78 | +# Copyright (C) 2015 Canonical Ltd. |
79 | +# |
80 | +# This program is free software; you can redistribute it and/or modify |
81 | +# it under the terms of the GNU General Public License version 3, as published |
82 | +# by the Free Software Foundation. |
83 | +# |
84 | +# This program is distributed in the hope that it will be useful, |
85 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
86 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
87 | +# GNU General Public License for more details. |
88 | +# |
89 | +# You should have received a copy of the GNU General Public License |
90 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
91 | + |
92 | +import datetime |
93 | +import json |
94 | +import threading |
95 | + |
96 | +from email.utils import parsedate_to_datetime |
97 | +from http.server import BaseHTTPRequestHandler, HTTPServer |
98 | + |
99 | + |
100 | +class MyHandler(BaseHTTPRequestHandler): |
101 | + |
102 | + def do_HEAD(self): |
103 | + self.send_response(200) |
104 | + self.end_headers(); |
105 | + |
106 | + def date_time_string(self): |
107 | + if self.path == '/muchearlier': |
108 | + ctime = parsedate_to_datetime(self.headers['Date']) |
109 | + value = ctime + datetime.timedelta(days=10000) |
110 | + return value.strftime('%a, %d %b %Y %H:%M:%S GMT') |
111 | + elif self.path == '/muchlater': |
112 | + ctime = parsedate_to_datetime(self.headers['Date']) |
113 | + value = ctime - datetime.timedelta(days=10000) |
114 | + return value.strftime('%a, %d %b %Y %H:%M:%S GMT') |
115 | + else: |
116 | + return 'Thu, 01 Jan 1970 00:00:10 GMT' |
117 | + |
118 | + |
119 | +def run_server(): |
120 | + server_address = ('', 8000) |
121 | + httpd = HTTPServer(server_address, MyHandler) |
122 | + while True: |
123 | + httpd.handle_request() |
124 | + |
125 | + |
126 | +def run_mocked_settings(): |
127 | + t = threading.Thread(target=run_server) |
128 | + t.start() |
129 | + |
130 | + |
131 | +run_mocked_settings() |
132 | |
133 | === modified file 'libubuntuoneauth/tests/test_token.cpp' |
134 | --- libubuntuoneauth/tests/test_token.cpp 2015-05-11 14:25:00 +0000 |
135 | +++ libubuntuoneauth/tests/test_token.cpp 2015-12-07 21:37:17 +0000 |
136 | @@ -1,5 +1,5 @@ |
137 | /* |
138 | - * Copyright 2013 Canonical Ltd. |
139 | + * Copyright 2013-2015 Canonical Ltd. |
140 | * |
141 | * This library is free software; you can redistribute it and/or |
142 | * modify it under the terms of version 3 of the GNU Lesser General Public |
143 | @@ -15,6 +15,7 @@ |
144 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
145 | * Boston, MA 02110-1301, USA. |
146 | */ |
147 | +#include <QDir> |
148 | #include <QHostInfo> |
149 | #include <QUuid> |
150 | |
151 | @@ -25,8 +26,16 @@ |
152 | using namespace UbuntuOne; |
153 | |
154 | |
155 | +void TestToken::cleanupTestCase() |
156 | +{ |
157 | + qputenv("SSO_AUTH_BASE_URL", old_base_url.toUtf8().data()); |
158 | + process->close(); |
159 | + process->deleteLater(); |
160 | +} |
161 | + |
162 | TestToken::TestToken() |
163 | - : test_hostname(QHostInfo::localHostName()) |
164 | + : test_hostname(QHostInfo::localHostName()), |
165 | + old_base_url("") |
166 | { |
167 | } |
168 | |
169 | @@ -96,6 +105,98 @@ |
170 | delete token; |
171 | } |
172 | |
173 | +void TestToken::testSignUrl() |
174 | +{ |
175 | + Token *token = new Token("a", "b", "c", "d"); |
176 | + auto result = token->signUrl(QStringLiteral("https://login.ubuntu.com"), |
177 | + QStringLiteral("GET")); |
178 | + QVERIFY(result.startsWith("OAuth oauth_consumer_key")); |
179 | + delete token; |
180 | +} |
181 | + |
182 | +void TestToken::testGetServerTimestamp() |
183 | +{ |
184 | + Token *token = new Token("a", "b", "c", "d"); |
185 | + auto result = token->getServerTimestamp(); |
186 | + delete token; |
187 | + |
188 | + QCOMPARE(result.toTime_t(), (uint)time(NULL)); |
189 | +} |
190 | + |
191 | +void TestToken::testGetServerTimestampMuchEarlier() |
192 | +{ |
193 | + old_base_url = qgetenv("SSO_AUTH_BASE_URL"); |
194 | + qputenv("SSO_AUTH_BASE_URL", "http://localhost:8000/muchearlier"); |
195 | + qputenv("U1_TEST_TIMESTAMP", "Thu, 01 Jan 1970 04:32:16 GMT"); |
196 | + |
197 | + auto _app = new QCoreApplication(argc, argv); |
198 | + |
199 | + QDateTime result; |
200 | + QTimer::singleShot(0, [this, &result, &_app](){ |
201 | + process = new QProcess(this); |
202 | + QSignalSpy spy(process, SIGNAL(started())); |
203 | + QString program = "python3"; |
204 | + QString script = QDir::currentPath() + "/mock_sso_server.py"; |
205 | + process->start(program, QStringList() << script); |
206 | + QTRY_COMPARE(spy.count(), 1); |
207 | + |
208 | + // Wait for server to start |
209 | + QTimer timer; |
210 | + QSignalSpy spy2(&timer, SIGNAL(timeout())); |
211 | + timer.setInterval(2000); |
212 | + timer.setSingleShot(true); |
213 | + timer.start(); |
214 | + QTRY_COMPARE(spy2.count(), 1); |
215 | + |
216 | + Token *token = new Token("a", "b", "c", "d"); |
217 | + result = token->getServerTimestamp(); |
218 | + delete token; |
219 | + |
220 | + _app->quit(); |
221 | + }); |
222 | + |
223 | + _app->exec(); |
224 | + |
225 | + QCOMPARE(result.toTime_t(), (uint)864016336); |
226 | +} |
227 | + |
228 | +void TestToken::testGetServerTimestampMuchLater() |
229 | +{ |
230 | + old_base_url = qgetenv("SSO_AUTH_BASE_URL"); |
231 | + qputenv("SSO_AUTH_BASE_URL", "http://localhost:8000/muchlater"); |
232 | + qputenv("U1_TEST_TIMESTAMP", "Mon, 18 Jan 2038 22:14:07 GMT"); |
233 | + |
234 | + auto _app = new QCoreApplication(argc, argv); |
235 | + |
236 | + QDateTime result; |
237 | + QTimer::singleShot(0, [this, &result, &_app](){ |
238 | + process = new QProcess(this); |
239 | + QSignalSpy spy(process, SIGNAL(started())); |
240 | + QString program = "python3"; |
241 | + QString script = QDir::currentPath() + "/mock_sso_server.py"; |
242 | + process->start(program, QStringList() << script); |
243 | + QTRY_COMPARE(spy.count(), 1); |
244 | + |
245 | + // Wait for server to start |
246 | + QTimer timer; |
247 | + QSignalSpy spy2(&timer, SIGNAL(timeout())); |
248 | + timer.setInterval(2000); |
249 | + timer.setSingleShot(true); |
250 | + timer.start(); |
251 | + QTRY_COMPARE(spy2.count(), 1); |
252 | + |
253 | + Token *token = new Token("a", "b", "c", "d"); |
254 | + result = token->getServerTimestamp(); |
255 | + delete token; |
256 | + |
257 | + _app->quit(); |
258 | + }); |
259 | + |
260 | + _app->exec(); |
261 | + |
262 | + QCOMPARE(result.toTime_t(), (uint)1283465647); |
263 | +} |
264 | + |
265 | void TestToken::testTimesCached() |
266 | { |
267 | Token *token = Token::fromQuery("consumer_key=c&consumer_secret=c_s&name=Name+%40+hostname&token=t&token_secret=t_s&updated=2014-08-11+18%3A40%3A20.777777&created=2014-08-11+18%3A40%3A20.777777"); |
268 | |
269 | === modified file 'libubuntuoneauth/tests/test_token.h' |
270 | --- libubuntuoneauth/tests/test_token.h 2014-09-09 13:53:07 +0000 |
271 | +++ libubuntuoneauth/tests/test_token.h 2015-12-07 21:37:17 +0000 |
272 | @@ -1,5 +1,5 @@ |
273 | /* |
274 | - * Copyright 2013 Canonical Ltd. |
275 | + * Copyright 2013-2015 Canonical Ltd. |
276 | * |
277 | * This library is free software; you can redistribute it and/or |
278 | * modify it under the terms of version 3 of the GNU Lesser General Public |
279 | @@ -18,6 +18,7 @@ |
280 | #ifndef _TEST_TOKEN_H_ |
281 | #define _TEST_TOKEN_H_ |
282 | |
283 | +#include <QProcess> |
284 | #include <QtTest/QtTest> |
285 | |
286 | class TestToken: public QObject |
287 | @@ -26,10 +27,17 @@ |
288 | public: |
289 | TestToken(); |
290 | |
291 | + int argc; |
292 | + char** argv; |
293 | + |
294 | private: |
295 | QString test_hostname; |
296 | + QProcess *process; |
297 | + QString old_base_url;; |
298 | |
299 | private slots: |
300 | + void cleanupTestCase(); |
301 | + |
302 | void testEmptyToken(); |
303 | void testTokenArgs(); |
304 | void testTokenCopy(); |
305 | @@ -40,6 +48,11 @@ |
306 | void testTokenName(); |
307 | |
308 | void testSignUrlEmpty(); |
309 | + void testSignUrl(); |
310 | + |
311 | + void testGetServerTimestamp(); |
312 | + void testGetServerTimestampMuchEarlier(); |
313 | + void testGetServerTimestampMuchLater(); |
314 | |
315 | void testTimesCached(); |
316 | void testCreatedParsed(); |
317 | |
318 | === modified file 'libubuntuoneauth/token.cpp' |
319 | --- libubuntuoneauth/token.cpp 2015-05-06 09:14:54 +0000 |
320 | +++ libubuntuoneauth/token.cpp 2015-12-07 21:37:17 +0000 |
321 | @@ -1,5 +1,5 @@ |
322 | /* |
323 | - * Copyright 2013 Canonical Ltd. |
324 | + * Copyright 2013-2015 Canonical Ltd. |
325 | * |
326 | * This library is free software; you can redistribute it and/or |
327 | * modify it under the terms of version 3 of the GNU Lesser General Public |
328 | @@ -15,16 +15,20 @@ |
329 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
330 | * Boston, MA 02110-1301, USA. |
331 | */ |
332 | +#include "token.h" |
333 | +#include "ssoservice.h" |
334 | + |
335 | #include <stdlib.h> |
336 | #include <oauth.h> |
337 | |
338 | +#include <QCoreApplication> |
339 | #include <QHash> |
340 | #include <QHostInfo> |
341 | +#include <QNetworkReply> |
342 | +#include <QNetworkRequest> |
343 | #include <QStringList> |
344 | #include <QUrl> |
345 | |
346 | -#include "token.h" |
347 | - |
348 | #define TOKEN_NAME_KEY "name" |
349 | #define TOKEN_TOKEN_KEY "token" |
350 | #define TOKEN_TOKEN_SEC_KEY "token_secret" |
351 | @@ -33,6 +37,8 @@ |
352 | #define TOKEN_UPDATED_KEY "updated" |
353 | #define TOKEN_CREATED_KEY "created" |
354 | |
355 | +#define TIMESTAMP_CHECK_INTERVAL (60 * 60) // Seconds/minute * minutes |
356 | + |
357 | |
358 | namespace UbuntuOne { |
359 | |
360 | @@ -128,7 +134,7 @@ |
361 | /** |
362 | * \fn QDateTime Token::updated() |
363 | * |
364 | - * Retruns a QDateTime representing the time the token was last updated on |
365 | + * Returns a QDateTime representing the time the token was last updated on |
366 | * the server, or empty if unknown. |
367 | */ |
368 | QDateTime Token::updated() const |
369 | @@ -141,6 +147,95 @@ |
370 | } |
371 | |
372 | /** |
373 | + * \fn QDateTime Token::getServerTimestamp() |
374 | + * |
375 | + * Returns a QDateTime representing the current time known on the |
376 | + * Ubuntu One authentication server, or current local time on errors, |
377 | + * or when a QCoreApplication instance is not running. |
378 | + */ |
379 | + QDateTime Token::getServerTimestamp() const |
380 | + { |
381 | + // The DateTime object to return, defaulting to current time |
382 | + QDateTime _dt = QDateTime::currentDateTimeUtc(); |
383 | + |
384 | + // The timestamp of the client to send to the server. |
385 | + QDateTime _clientDate(_dt); |
386 | + auto _testDate = qgetenv("U1_TEST_TIMESTAMP"); |
387 | + if (_testDate != "") { |
388 | + _clientDate = QDateTime::fromString(_testDate, Qt::RFC2822Date); |
389 | + } |
390 | + |
391 | + auto _app = QCoreApplication::instance(); |
392 | + if (_app != nullptr) { |
393 | + QSharedPointer<QNetworkAccessManager> _nam(new QNetworkAccessManager()); |
394 | + QUrl _url{SSOService::getAuthBaseUrl()}; |
395 | + QSharedPointer<QNetworkRequest> _req(new QNetworkRequest(_url)); |
396 | + _req->setRawHeader("Cache-Control", "no-cache"); |
397 | + _req->setRawHeader("Date", |
398 | + _clientDate.toString(Qt::RFC2822Date).toUtf8().data()); |
399 | + |
400 | + qDebug() << "Getting timestamp from server:" << _url.toString(); |
401 | + |
402 | + auto _reply = _nam->head(*_req); |
403 | + QEventLoop _loop; |
404 | + QObject::connect(_reply, &QNetworkReply::finished, |
405 | + [&_loop, &_reply, &_dt]() { |
406 | + auto _date = _reply->rawHeader("Date"); |
407 | + _dt = QDateTime::fromString(_date, |
408 | + Qt::RFC2822Date); |
409 | + qDebug() << "Got server timestamp:" |
410 | + << _dt.toTime_t(); |
411 | + _loop.quit(); |
412 | + }); |
413 | + typedef void(QNetworkReply::*QNetworkReplyErrorSignal)(QNetworkReply::NetworkError); |
414 | + QObject::connect(_reply, static_cast<QNetworkReplyErrorSignal>(&QNetworkReply::error), |
415 | + [&_loop, &_reply](QNetworkReply::NetworkError) { |
416 | + qCritical() << "Error fetching server timestamp:" |
417 | + << _reply->readAll(); |
418 | + _loop.quit(); |
419 | + }); |
420 | + |
421 | + _loop.exec(); |
422 | + } else { |
423 | + qWarning() << "No main loop, defaulting to local timestamp."; |
424 | + } |
425 | + return _dt; |
426 | + } |
427 | + |
428 | + /** |
429 | + * \fn QUrl Token::addOAuthTimestamp(const QString url) |
430 | + * |
431 | + * Returns a QUrl with the oauth_timestamp value added to the query string |
432 | + */ |
433 | + QUrl Token::addOAuthTimestamp(const QString url) const |
434 | + { |
435 | + // A copy of the URL in case we need to fix the timestamp |
436 | + QUrl newurl{url}; |
437 | + |
438 | + // Get and use the server timestamp if necessary |
439 | + QDateTime _now = QDateTime::currentDateTimeUtc(); |
440 | + // Static variables for caching the time to check, and skew |
441 | + static uint _ts_check = 0; |
442 | + static int _ts_skew = 0; |
443 | + |
444 | + QDateTime timestamp; |
445 | + if (_ts_check <= _now.toTime_t()) { |
446 | + timestamp = getServerTimestamp(); |
447 | + _ts_skew = timestamp.toTime_t() - _now.toTime_t(); |
448 | + } else { |
449 | + // QDateTime doesn't override + operator, create from time_t |
450 | + timestamp = QDateTime::fromTime_t(_now.toTime_t() + _ts_skew); |
451 | + } |
452 | + _ts_check = _now.toTime_t() + TIMESTAMP_CHECK_INTERVAL; |
453 | + char buf[11]; |
454 | + snprintf(buf, 11, "%010u", timestamp.toTime_t()); |
455 | + newurl.setQuery(newurl.query(QUrl::FullyEncoded) + |
456 | + "&oauth_timestamp=" + buf); |
457 | + |
458 | + return newurl; |
459 | + } |
460 | + |
461 | + /** |
462 | * \fn QString Token::signUrl(const QString url, const QString method, |
463 | * bool asQuery = false) |
464 | * |
465 | @@ -159,7 +254,9 @@ |
466 | return result; |
467 | } |
468 | |
469 | - argc = oauth_split_url_parameters(url.toUtf8().data(), &argv); |
470 | + QUrl copy(addOAuthTimestamp(url)); |
471 | + argc = oauth_split_url_parameters(copy.toString().toUtf8().data(), |
472 | + &argv); |
473 | // Fixup the URL as liboauth is escaping '+' to ' ' in it, incorrectly. |
474 | for (int a = 0; argv[0][a] != 0; a++) |
475 | argv[0][a] = argv[0][a] == ' ' ? '+' : argv[0][a]; |
476 | |
477 | === modified file 'libubuntuoneauth/token.h' |
478 | --- libubuntuoneauth/token.h 2015-05-06 08:59:44 +0000 |
479 | +++ libubuntuoneauth/token.h 2015-12-07 21:37:17 +0000 |
480 | @@ -1,5 +1,5 @@ |
481 | /* |
482 | - * Copyright 2013 Canonical Ltd. |
483 | + * Copyright 2013-2015 Canonical Ltd. |
484 | * |
485 | * This library is free software; you can redistribute it and/or |
486 | * modify it under the terms of version 3 of the GNU Lesser General Public |
487 | @@ -21,6 +21,7 @@ |
488 | #include <QDateTime> |
489 | #include <QHash> |
490 | #include <QString> |
491 | +#include <QUrl> |
492 | |
493 | |
494 | namespace UbuntuOne { |
495 | @@ -45,6 +46,8 @@ |
496 | QDateTime created() const; |
497 | QDateTime updated() const; |
498 | |
499 | + QDateTime getServerTimestamp() const; |
500 | + QUrl addOAuthTimestamp(const QString url) const; |
501 | QString signUrl(const QString url, const QString method, bool asQuery = false) const; |
502 | |
503 | static Token *fromQuery(const QString query); |
FAILED: Continuous integration, rev:219 jenkins. qa.ubuntu. com/job/ ubuntuone- credentials- ci/130/ jenkins. qa.ubuntu. com/job/ ubuntuone- credentials- wily-amd64- ci/7/console jenkins. qa.ubuntu. com/job/ ubuntuone- credentials- wily-armhf- ci/7/console jenkins. qa.ubuntu. com/job/ ubuntuone- credentials- wily-i386- ci/7/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntuone- credentials- ci/130/ rebuild
http://