bundle ssl certs; share con across all sync types

This commit is contained in:
Damien Elmes 2011-12-03 16:17:34 +09:00
parent 92352d4725
commit d148a6cf1b
5 changed files with 85 additions and 20 deletions

55
anki/ankiweb.certs Normal file
View file

@ -0,0 +1,55 @@
-----BEGIN CERTIFICATE-----
MIIFFzCCA/+gAwIBAgIRAP+ceCiXnKf8x8mBIBmTckswDQYJKoZIhvcNAQEFBQAw
cTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ29tb2RvIENBIExpbWl0ZWQxFzAVBgNV
BAMTDlBvc2l0aXZlU1NMIENBMB4XDTExMDkxNTAwMDAwMFoXDTE0MDkxNDIzNTk1
OVowTzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMRQwEgYDVQQL
EwtQb3NpdGl2ZVNTTDEUMBIGA1UEAxMLYW5raXdlYi5uZXQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDEDfc2WFrF5mkg4yrrbu/bxqW5SLu1qPp3Vtlv
+he8Fzkn44Zc8in7Q/t8pOxRMNq5nRjsKNUr51Zv206Z8aDzV6Mi2LtdHhADTOQW
UGa2+ANcvGJg6lCJ4WvQwcDIktO9kGgmlkMvuPAskF+nhRi7TlTaU8lhHlhMV5zu
G0XfXjPGitK1m5egIY78PJoVK+M/k44NMxi0sb+XgErXW0k6QdCZvba0z5Heks7+
aIFmLjx7bcEQxQS/+1nIK05nNrDPi7TymwZOM+b2T48t7+x9H9cjEeLUZsCiETja
SBLyj/2WLFYfH7jZuwylwcCvJ5PlnutAk7za3iASpGpUvWdFAgMBAAGjggHKMIIB
xjAfBgNVHSMEGDAWgBS4yhHpBjF528OUxugZKry7NRYxpDAdBgNVHQ4EFgQUGUTe
GYqlhmH/El7O10/hoPgIdqEwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYLKwYB
BAGyMQECAgcwLDAqBggrBgEFBQcCARYeaHR0cDovL3d3dy5wb3NpdGl2ZXNzbC5j
b20vQ1BTMGkGA1UdHwRiMGAwL6AtoCuGKWh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
L1Bvc2l0aXZlU1NMQ0EuY3JsMC2gK6AphidodHRwOi8vY3JsLmNvbW9kby5uZXQv
UG9zaXRpdmVTU0xDQS5jcmwwawYIKwYBBQUHAQEEXzBdMDUGCCsGAQUFBzAChilo
dHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9Qb3NpdGl2ZVNTTENBLmNydDAkBggrBgEF
BQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMCcGA1UdEQQgMB6CC2Fua2l3
ZWIubmV0gg93d3cuYW5raXdlYi5uZXQwDQYJKoZIhvcNAQEFBQADggEBAI6Mcuwd
OQTvTkeZ45j2VcI1hR/nqSf2VnisxRQxNRr+n8grjt1ulqYJWJyOrocUINW7XyoJ
jHcFpS30m/E4ZedaHXq++hJqjat140r5TRcBigAHnZj7u69hjAhwG/A6Er0JFbX+
eCwe1SCBUgDLGhcNA4o3cykmgK6qG/drj5/CVwpTVKzQ65JGxEMgWehELraPzbx9
mi3e9BMSC11eEsE6O0CpBL+ENcXngYpyi1R3GYFce9oFk+ps/1yYiUstgStq4obJ
8MdDZKB8qOLFPe097FGRcOz1JRDYDVD8JQ+d+o4T3/EHuxZ2EJXhAXJDc/FoKzru
Pb1JBxNB1O0QCmE=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----

View file

@ -43,6 +43,8 @@ SYNC_HOST = os.environ.get("SYNC_HOST") or "dev.ankiweb.net"
SYNC_PORT = int(os.environ.get("SYNC_PORT") or 80)
SYNC_URL = "http://%s:%d/sync/" % (SYNC_HOST, SYNC_PORT)
SYNC_VER = 0
HTTP_CERTS = os.path.join(os.path.basename(__file__), "ankiweb.certs")
HTTP_TIMEOUT = 60
# deck schema
SCHEMA_VERSION = 1

View file

@ -7,7 +7,7 @@ from cStringIO import StringIO
from datetime import date
from anki.db import DB
from anki.errors import *
from anki.utils import ids2str, checksum, intTime
from anki.utils import ids2str, checksum, intTime, httpCon
from anki.consts import *
from anki.lang import _
from hooks import runHook
@ -383,7 +383,7 @@ class HttpSyncer(object):
# retrieving a host key for future operations
def hostKey(self, pw):
h = httplib2.Http(timeout=60)
h = httpCon()
resp, cont = h.request(
SYNC_URL+"hostKey?" + urllib.urlencode(dict(u=self.user,p=pw)))
if resp['status'] != '200':
@ -452,11 +452,10 @@ class RemoteServer(Syncer, HttpSyncer):
def __init__(self, user, hkey):
self.user = user
self.hkey = hkey
self.con = None
self.con = httpCon()
def meta(self):
h = httplib2.Http(timeout=60)
resp, cont = h.request(
resp, cont = self.con.request(
SYNC_URL+"meta?" + urllib.urlencode(dict(u=self.user,v=SYNC_VER)))
# fixme: convert these into easily-catchable errors
if resp['status'] in ('503', '504'):
@ -470,7 +469,6 @@ class RemoteServer(Syncer, HttpSyncer):
return simplejson.loads(cont)
def applyChanges(self, **kw):
self.con = httplib2.Http(timeout=60)
return self._run("applyChanges", kw)
def chunk(self, **kw):
@ -495,16 +493,14 @@ class RemoteServer(Syncer, HttpSyncer):
class FullSyncer(HttpSyncer):
def __init__(self, col, hkey):
def __init__(self, col, hkey, con):
self.col = col
self.hkey = hkey
def _con(self):
return httplib2.Http(timeout=60)
self.con = con
def download(self):
self.col.close()
resp, cont = self._con().request(
resp, cont = self.con.request(
SYNC_URL+"download?" + urllib.urlencode(self._vars()))
if resp['status'] != '200':
raise Exception("Invalid response code: %s" % resp['status'])
@ -518,7 +514,7 @@ class FullSyncer(HttpSyncer):
def upload(self):
self.col.beforeUpload()
assert self.postData(self._con(), "upload", open(self.col.path, "rb"),
assert self.postData(self.con, "upload", open(self.col.path, "rb"),
self._vars(), comp=6) == "OK"
# Media syncing
@ -589,9 +585,9 @@ class MediaSyncer(object):
class RemoteMediaServer(MediaSyncer, HttpSyncer):
def __init__(self, hkey):
def __init__(self, hkey, con):
self.hkey = hkey
self.con = httplib2.Http(timeout=60)
self.con = con
def remove(self, **kw):
return simplejson.loads(

View file

@ -3,9 +3,10 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import re, os, random, time, types, math, htmlentitydefs, subprocess, \
tempfile, shutil, string
tempfile, shutil, string, httplib2
from hashlib import sha1
from anki.lang import _, ngettext
from anki.consts import *
import locale, sys
if sys.version_info[1] < 5:
@ -297,3 +298,13 @@ def call(argv, wait=True, **kwargs):
isMac = sys.platform.startswith("darwin")
isWin = sys.platform.startswith("win32")
# OS helpers
##############################################################################
def httpCon():
disable = os.environ.get("SSL_NOVALIDATE") or False
return httplib2.Http(
timeout=HTTP_TIMEOUT,
disable_ssl_certificate_validation=disable,
ca_certs=HTTP_CERTS)

View file

@ -4,7 +4,7 @@ import nose, os, tempfile, shutil, time
from tests.shared import assertException
from anki.errors import *
from anki.utils import intTime
from anki.utils import intTime, httpCon
from anki.sync import Syncer, FullSyncer, LocalServer, RemoteServer, \
MediaSyncer, RemoteMediaServer
from anki.notes import Note
@ -65,7 +65,7 @@ def test_hkey():
def test_download():
if not TEST_REMOTE:
return
f = FullSyncer(ts.client.col, "abc")
f = FullSyncer(ts.client.col, "abc", ts.server.con)
assertException(Exception, f.download)
f.hkey = TEST_HKEY
f.download()
@ -77,7 +77,7 @@ def test_remoteSync():
# not yet associated, so will require a full sync
assert ts.client.sync() == "fullSync"
# upload
f = FullSyncer(ts.client.col, TEST_HKEY)
f = FullSyncer(ts.client.col, TEST_HKEY, ts.server.con)
f.upload()
ts.client.col.reopen()
# should report no changes
@ -89,7 +89,7 @@ def test_remoteSync():
assert ts.client.sync() == "noChanges"
# downloading the remote col should give us the same mod
lmod = ts.client.col.mod
f = FullSyncer(ts.client.col, TEST_HKEY)
f = FullSyncer(ts.client.col, TEST_HKEY, ts.server.con)
f.download()
d = aopen(ts.client.col.path)
assert d.mod == lmod
@ -101,7 +101,8 @@ def test_remoteSync():
def setup_remoteMedia():
setup_basic()
ts.server = RemoteMediaServer(TEST_HKEY)
con = httpCon()
ts.server = RemoteMediaServer(TEST_HKEY, con)
ts.server2 = RemoteServer(TEST_USER, TEST_HKEY)
ts.client = MediaSyncer(ts.deck1, ts.server)