Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Hiro
GetTor
Commits
7b052eba
Commit
7b052eba
authored
Feb 15, 2016
by
ilv
Browse files
Merge branch 'develop'
parents
64510417
7735f5b6
Changes
8
Hide whitespace changes
Inline
Side-by-side
gettor/core.py
View file @
7b052eba
...
...
@@ -253,43 +253,49 @@ class Core(object):
t32
,
t64
=
[
t
for
t
in
providers
[
pname
].
split
(
","
)
if
t
]
link
,
signature
,
chs32
=
[
l
for
l
in
t32
.
split
(
"$"
)
if
l
]
link
=
"%s: %s"
%
(
pname
,
link
)
links32
[
link
]
=
signature
link
,
signature
,
chs64
=
[
l
for
l
in
t64
.
split
(
"$"
)
if
l
]
link
=
"%s: %s"
%
(
pname
,
link
.
lstrip
())
links64
[
link
]
=
signature
else
:
link
,
signature
,
chs32
=
[
l
for
l
in
providers
[
pname
].
split
(
"$"
)
if
l
]
link
=
"%s: %s"
%
(
pname
,
link
)
links32
[
link
]
=
signature
#providers[pname] = providers[pname].replace(",", "")
#providers[pname] = providers[pname].replace("$", "\n\n")
### We will improve and add the verification section soon ###
# all packages are signed with same key
# (Tor Browser developers)
fingerprint
=
config
.
get
(
'key'
,
'fingerprint'
)
#
fingerprint = config.get('key', 'fingerprint')
# for now, english messages only
fingerprint_msg
=
self
.
_get_msg
(
'fingerprint'
,
'en'
)
fingerprint_msg
=
fingerprint_msg
%
fingerprint
#
fingerprint_msg = self._get_msg('fingerprint', 'en')
#
fingerprint_msg = fingerprint_msg % fingerprint
except
ConfigParser
.
Error
as
e
:
raise
InternalError
(
"%s"
%
str
(
e
))
# create the final links list with all providers
all_links
=
[]
msg
=
"Tor Browser %s-bit:"
%
arch
msg
=
"Tor Browser %s-bit:
\n
"
%
arch
for
link
in
links32
:
msg
=
"%s
\n
%s"
%
(
msg
,
link
)
all_links
.
append
(
msg
)
if
osys
==
'linux'
:
msg
=
"
\n\n\n
Tor Browser 64-bit:"
msg
=
"
\n\n\n
Tor Browser 64-bit:
\n
"
for
link
in
links64
:
msg
=
"%s
\n
%s"
%
(
msg
,
link
)
all_links
.
append
(
msg
)
### We will improve and add the verification section soon ###
"""
msg = "
\n\n\n
Tor Browser's signature %s-bit:" %
\
arch
for link in links32:
...
...
@@ -312,6 +318,9 @@ class Core(object):
msg = "SHA256 of Tor Browser 64-bit (advanced): %s
\n
" % chs64
all_links.append(msg)
"""
### end verification ###
"""
for key in providers.keys():
# get more friendly description of the provider
...
...
@@ -328,8 +337,9 @@ class Core(object):
raise InternalError("%s" % str(e))
"""
### We will improve and add the verification section soon ###
# add fingerprint after the links
all_links
.
append
(
fingerprint_msg
)
#
all_links.append(fingerprint_msg)
if
all_links
:
return
""
.
join
(
all_links
)
...
...
gettor/http.py
0 → 100644
View file @
7b052eba
# -*- coding: utf-8 -*-
#
# This file is part of GetTor.
#
# :authors: Israel Leiva <ilv@torproject.org>
# see also AUTHORS file
#
# :copyright: (c) 2008-2015, The Tor Project, Inc.
# (c) 2015, Israel Leiva
#
# :license: This is Free Software. See LICENSE for license information.
import
os
import
re
import
json
import
codecs
import
urllib2
import
ConfigParser
from
time
import
gmtime
,
strftime
import
core
import
utils
"""GetTor RESTful API"""
# currently supported locales for Tor Browser
LC
=
[
'ar'
,
'de'
,
'en-US'
,
'es-ES'
,
'fa'
,
'fr'
,
'it'
,
'ko'
,
'nl'
,
'pl'
,
'pt-PT'
,
'ru'
,
'tr'
,
'vi'
,
'zh-CN'
]
# https://gitweb.tpo/tor-browser-spec.git/tree/processes/VersionNumbers
# does not say anything about operating systems, so it's possible the
# notation might change in the future. We should always use the same three
# strings though: linux, windows, osx.
OS
=
{
'Linux'
:
'linux'
,
'Windows'
:
'windows'
,
'MacOS'
:
'osx'
}
# based on
# https://gitweb.tpo.org/tor-browser-spec.git/tree/processes/VersionNumbers
# except for the first one, which is based on current RecommendedTBBVersions
RE
=
{
'os'
:
'(.*)-(\w+)'
,
'alpha'
:
'\d\.\d(\.\d)*a\d+'
,
'beta'
:
'\d\.\d(\.\d)*b\d+'
,
'stable'
:
'\d\.\d(\.\d)*'
}
# strings to build names of packages depending on OS.
PKG
=
{
'windows'
:
'torbrowser-install-%s_%s.exe'
,
'linux'
:
'tor-browser-linux%s-%s_%s.tar.xz'
,
'osx'
:
'TorBrowser-%s-osx64_%s.dmg'
}
# bin and asc are used to build the download links for each version, os and lc
URL
=
{
'version'
:
'https://www.torproject.org/projects/torbrowser/RecommendedTBBVersions'
,
'bin'
:
'https://www.torproject.org/dist/torbrowser/%s/%s'
,
'asc'
:
'https://www.torproject.org/dist/torbrowser/%s/%s.asc'
}
class
ConfigError
(
Exception
):
pass
class
InternalError
(
Exception
):
pass
class
HTTP
(
object
):
""" Provide useful resources via RESTful API. """
def
__init__
(
self
,
cfg
=
None
):
""" Create new object by reading a configuration file.
:param: cfg (string) path of the configuration file.
"""
default_cfg
=
'http.cfg'
config
=
ConfigParser
.
ConfigParser
()
if
cfg
is
None
or
not
os
.
path
.
isfile
(
cfg
):
cfg
=
default_cfg
try
:
with
open
(
cfg
)
as
f
:
config
.
readfp
(
f
)
except
IOError
:
raise
ConfigError
(
"File %s not found!"
%
cfg
)
try
:
# path to static tree of API
self
.
tree
=
config
.
get
(
'general'
,
'tree'
)
# server that provides the RESTful API
self
.
server
=
config
.
get
(
'general'
,
'url'
)
# path to the links files
self
.
links_path
=
config
.
get
(
'general'
,
'links'
)
# path to mirrors in json
self
.
mirrors_path
=
config
.
get
(
'general'
,
'mirrors'
)
# we will ask gettor.core for the links
core_cfg
=
config
.
get
(
'general'
,
'core'
)
self
.
core
=
core
.
Core
(
core_cfg
)
except
ConfigParser
.
Error
as
e
:
raise
ConfigError
(
"Configuration error: %s"
%
str
(
e
))
except
core
.
ConfigError
as
e
:
raise
InternalError
(
"HTTP error: %s"
%
str
(
e
))
def
_is_json
(
self
,
my_json
):
""" Check if json generated is valid.
:param: my_json (string) data to ve verified.
:return: (bool) true if data is json-valid, false otherwise.
"""
try
:
json_object
=
json
.
loads
(
my_json
)
except
ValueError
,
e
:
return
False
return
True
def
_write_json
(
self
,
path
,
content
):
"""
"""
try
:
with
codecs
.
open
(
path
,
"w"
,
"utf-8"
)
as
jsonfile
:
# Make pretty json
json
.
dump
(
content
,
jsonfile
,
sort_keys
=
True
,
indent
=
4
,
separators
=
(
','
,
': '
),
encoding
=
"utf-8"
,
)
except
IOError
as
e
:
#logging.error("Couldn't write json: %s" % str(e))
print
"Error building %s: %s"
%
(
path
,
str
(
e
))
print
"%s built"
%
path
def
_get_provider_name
(
self
,
p
):
""" Return simplified version of provider's name.
:param: p (string) provider's name.
:return: (string) provider's name in lowercase and without spaces.
"""
p
=
p
.
replace
(
' '
,
'-'
)
return
p
.
lower
()
def
_add_links
(
self
,
lv
,
release
,
version
,
os
):
""" Add link for all locales in LC depending on given OS.
:param: lv (dict) latest version data structure.
:param: release (string) release to which add the links.
:param: version (string) version obtained from tpo.
:param: os (string) operating system.
"""
for
lc
in
LC
:
if
os
==
'linux'
:
pkg32
=
PKG
[
'linux'
]
%
(
'32'
,
version
,
lc
)
link_bin32
=
URL
[
'bin'
]
%
(
version
,
pkg32
)
link_asc32
=
URL
[
'asc'
]
%
(
version
,
pkg32
)
pkg64
=
PKG
[
'linux'
]
%
(
'64'
,
version
,
lc
)
link_bin64
=
URL
[
'bin'
]
%
(
version
,
pkg64
)
link_asc64
=
URL
[
'asc'
]
%
(
version
,
pkg64
)
lv
[
release
][
'downloads'
][
os
][
lc
]
=
{
'binary32'
:
link_bin32
,
'signature32'
:
link_asc32
,
'binary64'
:
link_bin64
,
'signature64'
:
link_asc64
,
}
else
:
if
os
==
'windows'
:
pkg
=
PKG
[
'windows'
]
%
(
version
,
lc
)
elif
os
==
'osx'
:
pkg
=
PKG
[
'osx'
]
%
(
version
,
lc
)
else
:
continue
link_bin
=
URL
[
'bin'
]
%
(
version
,
pkg
)
link_asc
=
URL
[
'asc'
]
%
(
version
,
pkg
)
lv
[
release
][
'downloads'
][
os
][
lc
]
=
{
'binary'
:
link_bin
,
'signature'
:
link_asc
}
def
_load_latest_version
(
self
):
""" Load latest version data. """
response
=
urllib2
.
urlopen
(
URL
[
'version'
])
json_response
=
json
.
load
(
response
)
lv
=
{
'stable'
:
{
'latest_version'
:
''
,
'downloads'
:
{}
},
'alpha'
:
{
'latest_version'
:
''
,
'downloads'
:
{}
},
'beta'
:
{
'latest_version'
:
''
,
'downloads'
:
{}
}
}
self
.
releases
=
{
'alpha'
:
'%s/latest/alpha'
%
self
.
server
,
'beta'
:
'%s/latest/beta'
%
self
.
server
,
'stable'
:
'%s/latest/stable'
%
self
.
server
,
'updated_at'
:
strftime
(
"%Y-%m-%d %H:%M:%S"
,
gmtime
())
}
# one iteration to find the latest version for each release
for
v
in
json_response
:
# latest version for each release
if
not
re
.
match
(
RE
[
'os'
],
v
):
if
re
.
match
(
RE
[
'alpha'
],
v
):
if
v
>
lv
[
'alpha'
][
'latest_version'
]:
# we'll use the latest one
lv
[
'alpha'
][
'latest_version'
]
=
v
elif
re
.
match
(
RE
[
'beta'
],
v
):
if
v
>
lv
[
'beta'
][
'latest_version'
]:
# we'll use the latest one
lv
[
'beta'
][
'latest_version'
]
=
v
elif
re
.
match
(
RE
[
'stable'
],
v
):
if
v
>
lv
[
'stable'
][
'latest_version'
]:
# we'll use the latest one
lv
[
'stable'
][
'latest_version'
]
=
v
latest_alpha
=
lv
[
'alpha'
][
'latest_version'
]
latest_beta
=
lv
[
'beta'
][
'latest_version'
]
latest_stable
=
lv
[
'stable'
][
'latest_version'
]
# another iteration to add the links
for
v
in
json_response
:
# based on current RecommendedTBBVersions scheme
# for each release and for each os we build links for all locales
if
re
.
match
(
RE
[
'os'
],
v
):
m
=
re
.
match
(
RE
[
'os'
],
v
)
version
=
m
.
group
(
1
)
osys
=
m
.
group
(
2
)
if
osys
in
OS
:
if
latest_alpha
and
version
==
latest_alpha
\
and
re
.
match
(
RE
[
'alpha'
],
version
):
lv
[
'alpha'
][
'downloads'
][
OS
[
osys
]]
=
{}
self
.
_add_links
(
lv
,
'alpha'
,
version
,
OS
[
osys
])
elif
latest_beta
and
version
==
latest_beta
\
and
re
.
match
(
RE
[
'beta'
],
version
):
lv
[
'beta'
][
'downloads'
][
OS
[
osys
]]
=
{}
self
.
_add_links
(
lv
,
'beta'
,
version
,
OS
[
osys
])
elif
latest_stable
and
version
==
latest_stable
\
and
re
.
match
(
RE
[
'stable'
],
version
):
lv
[
'stable'
][
'downloads'
][
OS
[
osys
]]
=
{}
self
.
_add_links
(
lv
,
'stable'
,
version
,
OS
[
osys
])
lv
[
'updated_at'
]
=
strftime
(
"%Y-%m-%d %H:%M:%S"
,
gmtime
())
self
.
lv
=
lv
def
_load_links
(
self
):
""" Load links and providers data. """
links_files
=
[]
# look for files ending with .links in links_path
p
=
re
.
compile
(
'.*\.links$'
)
for
name
in
os
.
listdir
(
self
.
links_path
):
path
=
os
.
path
.
abspath
(
os
.
path
.
join
(
self
.
links_path
,
name
))
if
os
.
path
.
isfile
(
path
)
and
p
.
match
(
path
):
links_files
.
append
(
path
)
links
=
{}
providers
=
{}
supported_os
=
self
.
core
.
get_supported_os
()
supported_lc
=
self
.
core
.
get_supported_lc
()
for
name
in
links_files
:
config
=
ConfigParser
.
ConfigParser
()
try
:
with
open
(
name
)
as
f
:
config
.
readfp
(
f
)
except
IOError
:
raise
InternalError
(
"File %s not found!"
%
name
)
try
:
pname
=
config
.
get
(
'provider'
,
'name'
)
pname
=
self
.
_get_provider_name
(
pname
)
# build providers dict
providers
[
pname
]
=
'%s/providers/%s'
%
(
self
.
server
,
pname
)
providers
[
'updated_at'
]
=
strftime
(
"%Y-%m-%d %H:%M:%S"
,
gmtime
()
)
self
.
providers
=
providers
links
[
pname
]
=
{}
# build links data.
for
osys
in
supported_os
:
links
[
pname
][
osys
]
=
{}
for
lc
in
supported_lc
:
links
[
pname
][
osys
][
lc
]
=
{}
for
osys
in
supported_os
:
for
lc
in
supported_lc
:
l_str
=
config
.
get
(
osys
,
lc
)
# linux has 32 and 64 bit packages
if
osys
==
'linux'
:
l32_str
,
l64_str
=
l_str
.
split
(
','
)
link32
,
sig32
,
sha32
=
[
l
for
l
in
l32_str
.
split
(
"$"
)
if
l
]
link64
,
sig64
,
sha64
=
[
l
for
l
in
l64_str
.
split
(
"$"
)
if
l
]
link64
=
link64
.
lstrip
()
links
[
pname
][
osys
][
lc
][
'binary32'
]
=
link32
links
[
pname
][
osys
][
lc
][
'signature32'
]
=
sig32
links
[
pname
][
osys
][
lc
][
'sha256-32'
]
=
sha32
links
[
pname
][
osys
][
lc
][
'binary64'
]
=
link64
links
[
pname
][
osys
][
lc
][
'signature64'
]
=
sig64
links
[
pname
][
osys
][
lc
][
'sha256-64'
]
=
sha64
else
:
link
,
sig
,
sha
=
[
l
for
l
in
l_str
.
split
(
"$"
)
if
l
]
links
[
pname
][
osys
][
lc
][
'binary'
]
=
link
links
[
pname
][
osys
][
lc
][
'signature'
]
=
sig
links
[
pname
][
osys
][
lc
][
'sha256'
]
=
sha
except
ConfigParser
.
Error
as
e
:
raise
InternalError
(
"%s"
%
str
(
e
))
links
[
'updated_at'
]
=
strftime
(
"%Y-%m-%d %H:%M:%S"
,
gmtime
())
self
.
links
=
links
def
_load_mirrors
(
self
):
""" Load mirrors data. """
mirrors
=
[]
# json of mirrors should be obtained from get_mirrors.py
json_data
=
open
(
self
.
mirrors_path
).
read
()
mirrors
=
json
.
loads
(
json_data
)
self
.
mirrors
=
mirrors
def
_load_resources
(
self
):
""" Load available resources data. """
self
.
resources
=
{
'providers'
:
'%s/providers'
%
self
.
server
,
'mirrors'
:
'%s/mirrors'
%
self
.
server
,
'latest_version'
:
'%s/latest'
%
self
.
server
,
'updated_at'
:
strftime
(
"%Y-%m-%d %H:%M:%S"
,
gmtime
())
}
def
load_data
(
self
):
""" Load all data.
Since data is not frequently updated, we load all data before
running the RESTful API. Every time the links/mirrors/version
data is updated we should restart the API.
"""
self
.
_load_links
()
self
.
_load_mirrors
()
self
.
_load_resources
()
self
.
_load_latest_version
()
def
build
(
self
):
""" Build RESTful API. """
print
"Building API"
# resources
self
.
_write_json
(
os
.
path
.
join
(
self
.
tree
,
'api'
),
self
.
resources
)
api_path
=
os
.
path
.
join
(
self
.
tree
,
'api-content'
)
if
not
os
.
path
.
isdir
(
api_path
):
os
.
mkdir
(
api_path
)
# providers
self
.
_write_json
(
os
.
path
.
join
(
api_path
,
'providers'
),
self
.
providers
)
providers_path
=
os
.
path
.
join
(
api_path
,
'providers-content'
)
if
not
os
.
path
.
isdir
(
providers_path
):
os
.
mkdir
(
providers_path
)
for
provider
in
self
.
links
:
if
provider
==
'updated_at'
:
continue
self
.
_write_json
(
os
.
path
.
join
(
providers_path
,
provider
),
self
.
links
[
provider
]
)
provider_path
=
os
.
path
.
join
(
providers_path
,
"%s-content"
%
provider
)
if
not
os
.
path
.
isdir
(
provider_path
):
os
.
mkdir
(
provider_path
)
for
osys
in
self
.
links
[
provider
]:
self
.
_write_json
(
os
.
path
.
join
(
provider_path
,
osys
),
self
.
links
[
provider
][
osys
]
)
provider_os_path
=
os
.
path
.
join
(
provider_path
,
"%s-content"
%
osys
)
if
not
os
.
path
.
isdir
(
provider_os_path
):
os
.
mkdir
(
provider_os_path
)
for
lc
in
self
.
links
[
provider
][
osys
]:
self
.
_write_json
(
os
.
path
.
join
(
provider_os_path
,
lc
),
self
.
links
[
provider
][
osys
][
lc
]
)
# latest version
self
.
_write_json
(
os
.
path
.
join
(
api_path
,
'latest'
),
self
.
lv
)
lv_path
=
os
.
path
.
join
(
api_path
,
'latest-content'
)
if
not
os
.
path
.
isdir
(
lv_path
):
os
.
mkdir
(
lv_path
)
for
release
in
self
.
lv
:
if
release
==
'updated_at'
:
continue
self
.
_write_json
(
os
.
path
.
join
(
lv_path
,
release
),
self
.
lv
[
release
]
)
release_path
=
os
.
path
.
join
(
lv_path
,
"%s-content"
%
release
)
if
not
os
.
path
.
isdir
(
release_path
):
os
.
mkdir
(
release_path
)
for
osys
in
self
.
lv
[
release
][
'downloads'
]:
self
.
_write_json
(
os
.
path
.
join
(
release_path
,
osys
),
self
.
lv
[
release
][
'downloads'
][
osys
]
)
release_os_path
=
os
.
path
.
join
(
release_path
,
"%s-content"
%
osys
)
if
not
os
.
path
.
isdir
(
release_os_path
):
os
.
mkdir
(
release_os_path
)
for
lc
in
self
.
lv
[
release
][
'downloads'
][
osys
]:
self
.
_write_json
(
os
.
path
.
join
(
release_os_path
,
lc
),
self
.
lv
[
release
][
'downloads'
][
osys
][
lc
]
)
# mirrors
self
.
_write_json
(
os
.
path
.
join
(
api_path
,
'mirrors'
),
self
.
mirrors
)
gettor/smtp.py
View file @
7b052eba
...
...
@@ -33,6 +33,12 @@ import blacklist
"""SMTP module for processing email requests."""
OS
=
{
'osx'
:
'Mac OS X'
,
'linux'
:
'Linux'
,
'windows'
:
'Windows'
}
class
ConfigError
(
Exception
):
pass
...
...
@@ -368,7 +374,7 @@ class SMTP(object):
try
:
links_subject
=
self
.
_get_msg
(
'links_subject'
,
'en'
)
links_msg
=
self
.
_get_msg
(
'links_msg'
,
'en'
)
links_msg
=
links_msg
%
(
os
,
lc
,
links
)
links_msg
=
links_msg
%
(
os
,
links
)
self
.
_send_email
(
from_addr
,
...
...
lang/smtp/i18n/en/LC_MESSAGES/en.po
View file @
7b052eba
...
...
@@ -22,42 +22,28 @@ msgstr "The locale you requested '%s' is not supported."
#: Links message
msgid "links_msg"
msgstr "
Hello there! this is the 'GetTor' robot
.\n\
msgstr "
You requested Tor Browser for %s
.\n\
\n\
Below are the links for your request (Tor Browser for %s, %s package):\n\
You will need only one of the links below to download the bundle. If a link\n\
does not work for you, try the next one.\n\
\n\
%s\n\
\n\
===========================================================================\n\
Still need help? If you have any questions, trouble connecting to Tor\n\
network, or need to talk to a human, please contact our support team at:\n\
\n\
help@rt.torproject.org\n\
\n\
We are ready to answer your queries in English, Farsi, Chinese, Arabic,\n\
French and Spanish."
--\n\
GetTor"