Merge branch 'master' into onedrive

onedrive
eric 2019-04-19 12:23:19 -04:00
commit 62588e436f
14 changed files with 165 additions and 3145 deletions

View File

@ -38,7 +38,6 @@ class BibrecPage (Page.Page):
dc.load_from_database (os.id)
if not dc.files:
# NOTE: Error message
cherrypy.tools.rate_limiter.e404 ()
raise cherrypy.HTTPError (404, _('No ebook by that number.'))
# add these fields so we won't have to test for their existence later

View File

@ -44,18 +44,16 @@ from SearchPage import BookSearchPage, AuthorSearchPage, SubjectSearchPage, Book
from BibrecPage import BibrecPage
import CoverPages
import QRCodePage
import StatsPage
import CaptchaPage
import Sitemap
import Formatters
import RateLimiter
import Timer
plugins.Timer = Timer.TimerPlugin
if six.PY3:
CHERRYPY_CONFIG = ('/etc/autocat3.conf', os.path.expanduser ('~/.autocat3'))
CHERRYPY_CONFIG = (os.path.expanduser ('~/.autocat3'), '/etc/autocat3.conf')
# CCHERRYPY_CONFIG = ('/etc/autocat3.conf')
else:
CHERRYPY_CONFIG = ('/etc/autocat.conf', os.path.expanduser ('~/.autocat'))
@ -140,12 +138,6 @@ def main ():
Formatters.init ()
cherrypy.log ("Continuing App Init", context = 'ENGINE', severity = logging.INFO)
try:
cherrypy.tools.rate_limiter = RateLimiter.RateLimiterTool ()
except Exception as e:
tb = traceback.format_exc ()
cherrypy.log (tb, context = 'ENGINE', severity = logging.ERROR)
cherrypy.log ("Continuing App Init", context = 'ENGINE', severity = logging.INFO)
cherrypy.tools.I18nTool = i18n_tool.I18nTool ()
@ -169,8 +161,6 @@ def main ():
cherrypy.engine, params = GutenbergDatabase.get_connection_params (cherrypy.config))
cherrypy.engine.pool.subscribe ()
plugins.RateLimiterReset (cherrypy.engine).subscribe ()
plugins.RateLimiterDatabase (cherrypy.engine).subscribe ()
plugins.Timer (cherrypy.engine).subscribe ()
cherrypy.log ("Daemonizing", context = 'ENGINE', severity = logging.INFO)
@ -263,16 +253,7 @@ def main ():
controller = Page.NullPage ())
d.connect ('stats', r'/stats/',
controller = StatsPage.StatsPage ())
d.connect ('block', r'/stats/block/',
controller = RateLimiter.BlockPage ())
d.connect ('unblock', r'/stats/unblock/',
controller = RateLimiter.UnblockPage ())
d.connect ('traceback', r'/stats/traceback/',
controller = RateLimiter.TracebackPage ())
controller = Page.NullPage (), _static = True)
d.connect ('honeypot_send', r'/ebooks/send/megaupload/{id:\d+}.{filetype}',
controller = Page.NullPage (), _static = True)

View File

@ -21,7 +21,6 @@ netaddr = "*"
oauth = "*"
oauthlib = "*"
Pillow = "*"
psycopg2 = "*"
#pycurl = "*"
#PyGObject = "*"
pyparsing = "*"
@ -40,7 +39,7 @@ SQLAlchemy = "*"
#ufw = "*"
#unattended-upgrades = "*"
urllib3 = "*"
adns = "==1.4-py0"
psycopg2 = "==2.7.7"
[requires]
python_version = "3.6"

181
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "ee8fb05228d77d9d0e14c78195d3ead551470bbfb9d44c0cbe88444aefe72370"
"sha256": "faa368c84714ecc94bc3f9b3a0bb08d4d8075fe70ae633afb9909ad5ae4f0bd5"
},
"pipfile-spec": 6,
"requires": {
@ -16,13 +16,6 @@
]
},
"default": {
"adns": {
"hashes": [
"sha256:1176e63b66db007e8798150a9a7cfcca5d8a810ae488905f8b2b6b07e678f2ef"
],
"index": "pypi",
"version": "==1.4-py0"
},
"babel": {
"hashes": [
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
@ -62,11 +55,11 @@
},
"cherrypy": {
"hashes": [
"sha256:4dd2f59b5af93bd9ca85f1ed0bb8295cd0f5a8ee2b84d476374d4e070aa5c615",
"sha256:626e305bca3c5d56a16e5f7d64bc8a4e25d26c41be1779f585fad2608edbc4c8"
"sha256:3c7b27fd1af4964434d821cd139b8d05c8f7fe4f37ae146fddb3f861d80a1da7",
"sha256:6585c19b5e4faffa3613b5bf02c6a27dcc4c69a30d302aba819639a2af6fa48b"
],
"index": "pypi",
"version": "==18.1.0"
"version": "==18.1.1"
},
"colorama": {
"hashes": [
@ -123,41 +116,41 @@
},
"lxml": {
"hashes": [
"sha256:0358b9e9642bc7d39aac5cffe9884a99a5ca68e5e2c1b89e570ed60da9139908",
"sha256:091a359c4dafebbecd3959d9013f1b896b5371859165e4e50b01607a98d9e3e2",
"sha256:1998e4e60603c64bcc35af61b4331ab3af087457900d3980e18d190e17c3a697",
"sha256:2000b4088dee9a41f459fddaf6609bba48a435ce6374bb254c5ccdaa8928c5ba",
"sha256:2afb0064780d8aaf165875be5898c1866766e56175714fa5f9d055433e92d41d",
"sha256:2d8f1d9334a4e3ff176d096c14ded3100547d73440683567d85b8842a53180bb",
"sha256:2e38db22f6a3199fd63675e1b4bd795d676d906869047398f29f38ca55cb453a",
"sha256:3181f84649c1a1ca62b19ddf28436b1b2cb05ae6c7d2628f33872e713994c364",
"sha256:37462170dfd88af8431d04de6b236e6e9c06cda71e2ca26d88ef2332fd2a5237",
"sha256:3a9d8521c89bf6f2a929c3d12ad3ad7392c774c327ea809fd08a13be6b3bc05f",
"sha256:3d0bbd2e1a28b4429f24fd63a122a450ce9edb7a8063d070790092d7343a1aa4",
"sha256:483d60585ce3ee71929cea70949059f83850fa5e12deb9c094ed1c8c2ec73cbd",
"sha256:4888be27d5cba55ce94209baef5bcd7bbd7314a3d17021a5fc10000b3a5f737d",
"sha256:64b0d62e4209170a2a0c404c446ab83b941a0003e96604d2e4f4cb735f8a2254",
"sha256:68010900898fdf139ac08549c4dba8206c584070a960ffc530aebf0c6f2794ef",
"sha256:872ecb066de602a0099db98bd9e57f4cfc1d62f6093d94460c787737aa08f39e",
"sha256:88a32b03f2e4cd0e63f154cac76724709f40b3fc2f30139eb5d6f900521b44ed",
"sha256:b1dc7683da4e67ab2bebf266afa68098d681ae02ce570f0d1117312273d2b2ac",
"sha256:b29e27ce9371810250cb1528a771d047a9c7b0f79630dc7dc5815ff828f4273b",
"sha256:ce197559596370d985f1ce6b7051b52126849d8159040293bf8b98cb2b3e1f78",
"sha256:d45cf6daaf22584eff2175f48f82c4aa24d8e72a44913c5aff801819bb73d11f",
"sha256:e2ff9496322b2ce947ba4a7a5eb048158de9d6f3fe9efce29f1e8dd6878561e6",
"sha256:f7b979518ec1f294a41a707c007d54d0f3b3e1fd15d5b26b7e99b62b10d9a72e",
"sha256:f9c7268e9d16e34e50f8246c4f24cf7353764affd2bc971f0379514c246e3f6b",
"sha256:f9c839806089d79de588ee1dde2dae05dc1156d3355dfeb2b51fde84d9c960ad",
"sha256:ff962953e2389226adc4d355e34a98b0b800984399153c6678f2367b11b4d4b8"
"sha256:03984196d00670b2ab14ae0ea83d5cc0cfa4f5a42558afa9ab5fa745995328f5",
"sha256:0815b0c9f897468de6a386dc15917a0becf48cc92425613aa8bbfc7f0f82951f",
"sha256:175f3825f075cf02d15099eb52658457cf0ff103dcf11512b5d2583e1d40f58b",
"sha256:30e14c62d88d1e01a26936ecd1c6e784d4afc9aa002bba4321c5897937112616",
"sha256:3210da6f36cf4b835ff1be853962b22cc354d506f493b67a4303c88bbb40d57b",
"sha256:40f60819fbd5bad6e191ba1329bfafa09ab7f3f174b3d034d413ef5266963294",
"sha256:43b26a865a61549919f8a42e094dfdb62847113cf776d84bd6b60e4e3fc20ea3",
"sha256:4a03dd682f8e35a10234904e0b9508d705ff98cf962c5851ed052e9340df3d90",
"sha256:62f382cddf3d2e52cf266e161aa522d54fd624b8cc567bc18f573d9d50d40e8e",
"sha256:7b98f0325be8450da70aa4a796c4f06852949fe031878b4aa1d6c417a412f314",
"sha256:846a0739e595871041385d86d12af4b6999f921359b38affb99cdd6b54219a8f",
"sha256:a3080470559938a09a5d0ec558c005282e99ac77bf8211fb7b9a5c66390acd8d",
"sha256:ad841b78a476623955da270ab8d207c3c694aa5eba71f4792f65926dc46c6ee8",
"sha256:afdd75d9735e44c639ffd6258ce04a2de3b208f148072c02478162d0944d9da3",
"sha256:b4fbf9b552faff54742bcd0791ab1da5863363fb19047e68f6592be1ac2dab33",
"sha256:b90c4e32d6ec089d3fa3518436bdf5ce4d902a0787dbd9bb09f37afe8b994317",
"sha256:b91cfe4438c741aeff662d413fd2808ac901cc6229c838236840d11de4586d63",
"sha256:bdb0593a42070b0a5f138b79b872289ee73c8e25b3f0bea6564e795b55b6bcdd",
"sha256:c4e4bca2bb68ce22320297dfa1a7bf070a5b20bcbaec4ee023f83d2f6e76496f",
"sha256:cec4ab14af9eae8501be3266ff50c3c2aecc017ba1e86c160209bb4f0423df6a",
"sha256:e83b4b2bf029f5104bc1227dbb7bf5ace6fd8fabaebffcd4f8106fafc69fc45f",
"sha256:e995b3734a46d41ae60b6097f7c51ba9958648c6d1e0935b7e0ee446ee4abe22",
"sha256:f679d93dec7f7210575c85379a31322df4c46496f184ef650d3aba1484b38a2d",
"sha256:fd213bb5166e46974f113c8228daaef1732abc47cb561ce9c4c8eaed4bd3b09b",
"sha256:fdcb57b906dbc1f80666e6290e794ab8fb959a2e17aa5aee1758a85d1da4533f",
"sha256:ff424b01d090ffe1947ec7432b07f536912e0300458f9a7f48ea217dd8362b86"
],
"version": "==4.3.2"
"version": "==4.3.3"
},
"more-itertools": {
"hashes": [
"sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40",
"sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1"
"sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7",
"sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"
],
"version": "==6.0.0"
"version": "==7.0.0"
},
"netaddr": {
"hashes": [
@ -184,46 +177,42 @@
},
"pillow": {
"hashes": [
"sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e",
"sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7",
"sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a",
"sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3",
"sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1",
"sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1",
"sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7",
"sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1",
"sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3",
"sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055",
"sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf",
"sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f",
"sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f",
"sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239",
"sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe",
"sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c",
"sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697",
"sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494",
"sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356",
"sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6",
"sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000",
"sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f",
"sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c",
"sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca",
"sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8",
"sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3",
"sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad",
"sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9",
"sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc",
"sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e"
"sha256:15c056bfa284c30a7f265a41ac4cbbc93bdbfc0dfe0613b9cb8a8581b51a9e55",
"sha256:1a4e06ba4f74494ea0c58c24de2bb752818e9d504474ec95b0aa94f6b0a7e479",
"sha256:1c3c707c76be43c9e99cb7e3d5f1bee1c8e5be8b8a2a5eeee665efbf8ddde91a",
"sha256:1fd0b290203e3b0882d9605d807b03c0f47e3440f97824586c173eca0aadd99d",
"sha256:24114e4a6e1870c5a24b1da8f60d0ba77a0b4027907860188ea82bd3508c80eb",
"sha256:258d886a49b6b058cd7abb0ab4b2b85ce78669a857398e83e8b8e28b317b5abb",
"sha256:33c79b6dd6bc7f65079ab9ca5bebffb5f5d1141c689c9c6a7855776d1b09b7e8",
"sha256:367385fc797b2c31564c427430c7a8630db1a00bd040555dfc1d5c52e39fcd72",
"sha256:3c1884ff078fb8bf5f63d7d86921838b82ed4a7d0c027add773c2f38b3168754",
"sha256:44e5240e8f4f8861d748f2a58b3f04daadab5e22bfec896bf5434745f788f33f",
"sha256:46aa988e15f3ea72dddd81afe3839437b755fffddb5e173886f11460be909dce",
"sha256:74d90d499c9c736d52dd6d9b7221af5665b9c04f1767e35f5dd8694324bd4601",
"sha256:809c0a2ce9032cbcd7b5313f71af4bdc5c8c771cb86eb7559afd954cab82ebb5",
"sha256:85d1ef2cdafd5507c4221d201aaf62fc9276f8b0f71bd3933363e62a33abc734",
"sha256:8c3889c7681af77ecfa4431cd42a2885d093ecb811e81fbe5e203abc07e0995b",
"sha256:9218d81b9fca98d2c47d35d688a0cea0c42fd473159dfd5612dcb0483c63e40b",
"sha256:9aa4f3827992288edd37c9df345783a69ef58bd20cc02e64b36e44bcd157bbf1",
"sha256:9d80f44137a70b6f84c750d11019a3419f409c944526a95219bea0ac31f4dd91",
"sha256:b7ebd36128a2fe93991293f997e44be9286503c7530ace6a55b938b20be288d8",
"sha256:c4c78e2c71c257c136cdd43869fd3d5e34fc2162dc22e4a5406b0ebe86958239",
"sha256:c6a842537f887be1fe115d8abb5daa9bc8cc124e455ff995830cc785624a97af",
"sha256:cf0a2e040fdf5a6d95f4c286c6ef1df6b36c218b528c8a9158ec2452a804b9b8",
"sha256:cfd28aad6fc61f7a5d4ee556a997dc6e5555d9381d1390c00ecaf984d57e4232",
"sha256:dca5660e25932771460d4688ccbb515677caaf8595f3f3240ec16c117deff89a",
"sha256:de7aedc85918c2f887886442e50f52c1b93545606317956d65f342bd81cb4fc3",
"sha256:e6c0bbf8e277b74196e3140c35f9a1ae3eafd818f7f2d3a15819c49135d6c062"
],
"index": "pypi",
"version": "==5.4.1"
"version": "==6.0.0"
},
"portend": {
"hashes": [
"sha256:b7ce7d35ea262415297cbfea86226513e77b9ee5f631d3baa11992d663963719",
"sha256:f5c99a1aa1655733736bb0283fee6a1e115e18db500332bec8e24c43f320d8e8"
"sha256:507e1f76eb6deec0cc15045d1140a07874f44d02eec021e8fd383557d99fe93d",
"sha256:853d69e61d86aa1bc7a4976cb2f67efe1c92d3b41c47a5e6b8771d3c51b5bfd3"
],
"version": "==2.3"
"version": "==2.4"
},
"psycopg2": {
"hashes": [
@ -263,19 +252,19 @@
},
"pyparsing": {
"hashes": [
"sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a",
"sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3"
"sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
"sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
],
"index": "pypi",
"version": "==2.3.1"
"version": "==2.4.0"
},
"pytz": {
"hashes": [
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
"sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
"sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
],
"index": "pypi",
"version": "==2018.9"
"version": "==2019.1"
},
"qrcode": {
"hashes": [
@ -302,18 +291,18 @@
},
"regex": {
"hashes": [
"sha256:0306149889c1a1bec362511f737bc446245ddfcdbe4b556abdfc506ed46dfa47",
"sha256:4b08704a5939c698d2d5950b5dc950597613216cc8c01048efc0da860a0c3db9",
"sha256:6ba0eb777ada6887062c2620e6d644b011078d5d3dc09119ae7107285f6f95e9",
"sha256:7789cc323948792c4c62b269a56f2f2f9bc77d44e54fd81e01b12a967dd7244c",
"sha256:825143aadca0da7d26eeaf2ab0f8bc33921a5642e570ded92dde08c5aaebc65f",
"sha256:8fbd057faab28ce552d89c46f7a968e950f07e80752dfb93891dd11c6b0ee3b4",
"sha256:a41aabb0b9072a14f1e2e554f959ed6439b83610ed656edace9096a0b27e378e",
"sha256:d8807231aed332a1d0456d2088967b87e8c664222bed8e566384ca0ec0b43bfd",
"sha256:dfd89b642fe71f4e8a9906455d4147d453061377b650e6233ddd9ea822971360"
"sha256:020429dcf9b76cc7648a99c81b3a70154e45afebc81e0b85364457fe83b525e4",
"sha256:0552802b1c3f3c7e4fee8c85e904a13c48226020aa1a0593246888a1ac55aaaf",
"sha256:308965a80b92e1fec263ac1e4f1094317809a72bc4d26be2ec8a5fd026301175",
"sha256:4d627feef04eb626397aa7bdec772774f53d63a1dc7cc5ee4d1bd2786a769d19",
"sha256:93d1f9fcb1d25e0b4bd622eeba95b080262e7f8f55e5b43c76b8a5677e67334c",
"sha256:c3859bbf29b1345d694f069ddfe53d6907b0393fda5e3794c800ad02902d78e9",
"sha256:d56ce4c7b1a189094b9bee3b81c4aeb3f1ba3e375e91627ec8561b6ab483d0a8",
"sha256:ebc5ef4e10fa3312fa1967dc0a894e6bd985a046768171f042ac3974fadc9680",
"sha256:f9cd39066048066a4abe4c18fb213bc541339728005e72263f023742fb912585"
],
"index": "pypi",
"version": "==2019.3.12"
"version": "==2019.4.14"
},
"repoze.lru": {
"hashes": [
@ -375,17 +364,17 @@
},
"sqlalchemy": {
"hashes": [
"sha256:781fb7b9d194ed3fc596b8f0dd4623ff160e3e825dd8c15472376a438c19598b"
"sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319"
],
"index": "pypi",
"version": "==1.3.1"
"version": "==1.3.3"
},
"tempora": {
"hashes": [
"sha256:4951da790bd369f718dbe2287adbdc289dc2575a09278e77fad6131bcfe93097",
"sha256:f8abbbd486eca3340bd3d242417b203c861d4e113ef778cd5fb9535b2b32ae54"
"sha256:cb60b1d2b1664104e307f8e5269d7f4acdb077c82e35cd57246ae14a3427d2d6",
"sha256:d28a03d2f64ee81aec6e6bff374127ef306fe00c1b7e27c7ff1618344221a699"
],
"version": "==1.14"
"version": "==1.14.1"
},
"urllib3": {
"hashes": [

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
#!/usr/bin/env python
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
"""
StatsPage.py
Copyright 2009-2014 by Marcello Perathoner
Distributable under the GNU General Public License Version 3 or newer.
The appserver stats page.
"""
from __future__ import unicode_literals
import cherrypy
import BaseSearcher
import TemplatedPage
import asyncdns
import ipinfo
class StatsPage (TemplatedPage.TemplatedPage):
""" Output some statistics. """
CONTENT_TYPE = 'application/xhtml+xml; charset=UTF-8'
FORMATTER = 'html'
def index (self, **kwargs):
""" Output stats. """
backends = int (BaseSearcher.sql_get ("SELECT count (*) from pg_stat_activity"))
active_backends = int (BaseSearcher.sql_get (
"SELECT count (*) - 1 from pg_stat_activity where current_query !~ '^<IDLE>'"))
ipsessions = list (cherrypy.tools.rate_limiter.cache.values ()) # pylint: disable=E1101
adns = asyncdns.AsyncDNS ()
# blocked IPs
blocked = sorted ([s for s in ipsessions if s.get ('blocked', 0) >= 2],
key = lambda s: s.ips.sort_key ())
if 'resolve' in kwargs:
for d in blocked:
if d.ips.ipinfo is None:
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
# active IPs
active = sorted ([s for s in ipsessions if s.get ('active', False)],
key = lambda s: s.ips.sort_key ())
# busiest IPs
busiest = sorted ([s for s in active if s.get ('blocked', 0) < 2],
key = lambda x: -x.get ('rhits'))[:10]
if 'resolve' in kwargs:
for d in busiest:
if d.ips.ipinfo is None:
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
# IPs with most sessions
most_sessions = sorted ([s for s in active
if not s.ips.whitelisted and len (s.sessions) > 1],
key = lambda s: -len (s.sessions))[:10]
if 'resolve' in kwargs:
for d in most_sessions:
if d.ips.ipinfo is None:
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
adns.wait ()
adns.cancel ()
return self.output ('stats',
active = active,
blocked = blocked,
busiest = busiest,
most_sessions = most_sessions,
resolve = 'resolve' in kwargs,
rl = cherrypy.tools.rate_limiter, # pylint: disable=E1101
backends = backends,
active_backends = active_backends)

View File

@ -1,200 +0,0 @@
#!/usr/bin/env python
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
"""
asyncdns.py
Copyright 2013-14 by Marcello Perathoner
Distributable under the GNU General Public License Version 3 or newer.
Higher level interface to the GNU asynchronous DNS library.
"""
from __future__ import unicode_literals
import sys
import time
import adns
# pass this to __init__ to use Google Public DNS
RESOLV_CONF = 'nameserver 8.8.8.8'
# http://www.ietf.org/rfc/rfc1035.txt Domain Names
# http://www.ietf.org/rfc/rfc3490.txt IDNA
# http://www.ietf.org/rfc/rfc3492.txt Punycode
class AsyncDNS (object):
""" An asynchronous DNS resolver. """
def __init__ (self, resolv_conf = None):
if resolv_conf:
self.resolver = adns.init (
adns.iflags.noautosys + adns.iflags.noerrprint,
sys.stderr, # FIXME: adns version 1.2.2 will allow keyword params
resolv_conf)
else:
self.resolver = adns.init (
adns.iflags.noautosys + adns.iflags.noerrprint)
self._queries = {} # keeps query objects alive
def query (self, query, callback, rr = adns.rr.A):
""" Queue a query.
:param query: the query string (may contain unicode characters)
:param callback: function taking a tuple of answers
:param rr: the query rr type code
"""
if rr not in (adns.rr.PTR, adns.rr.PTRraw):
query = self.encode (query)
if rr in (adns.rr.PTR, adns.rr.PTRraw):
self._queries [self.resolver.submit_reverse (query, rr)] = callback, rr
else:
self._queries [self.resolver.submit (query, rr)] = callback, rr
def query_dnsbl (self, query, zone, callback, rr = adns.rr.A):
""" Queue a reverse dnsbl-type query. """
self._queries [self.resolver.submit_reverse_any (query, zone, rr)] = callback, rr
def done (self):
""" Are all queued queries answered? """
return not self._queries
def wait (self, timeout = 10):
""" Wait for the queries to complete. """
timeout += time.time ()
while self._queries and time.time () < timeout:
for q in self.resolver.completed (1):
answer = q.check ()
callback, rr = self._queries[q]
del self._queries[q]
# print (answer)
a0 = answer[0]
if a0 == 0:
callback (self.decode_answer (rr, answer[3]))
elif a0 == 101 and rr == adns.rr.A:
# got CNAME, wanted A: resubmit
self.query (answer[1], callback, rr)
# else
# pass
def decode_answer (self, rr, answers):
""" Decode the answer to unicode.
Supports only some rr types. You may override this to support
some more.
"""
if rr in (adns.rr.A, adns.rr.TXT):
# A records are ip addresses that need no decoding.
# TXT records may be anything, even binary data,
# so leave decoding to the caller.
return answers
if rr in (adns.rr.PTR, adns.rr.PTRraw, adns.rr.CNAME, adns.rr.NSraw):
return [ self.decode (host) for host in answers ]
if rr == adns.rr.MXraw:
return [ (prio, self.decode (host)) for (prio, host) in answers ]
if rr == adns.rr.SRVraw:
return [ (prio, weight, port, self.decode (host))
for (prio, weight, port, host) in answers ]
if rr in (adns.rr.SOA, adns.rr.SOAraw):
return [ (self.decode (mname), self.decode (rname),
serial, refresh, retry, expire, minimum)
for (mname, rname, serial, refresh,
retry, expire, minimum) in answers ]
# unsupported HINFO, RP, RPraw, NS, SRV, MX
return answers
@staticmethod
def encode (query):
""" Encode a unicode query to idna.
Result will still be of type unicode/str.
"""
return query.encode ('idna').decode ('ascii')
@staticmethod
def decode (answer):
""" Decode an answer to unicode. """
try:
return answer.decode ('idna')
except ValueError:
return answer.decode ('ascii', 'replace')
def cancel (self):
""" Cancel all pending queries. """
for q in self._queries.keys ():
q.cancel ()
self._queries.clear ()
def bulk_query (self, query_dict, rr):
""" Bulk lookup.
:param dict: on entry { query1: None, query2: None }
on exit { query1: (answer1, ), query2: (answer2a, answer2b) }
Note: you must call wait () after bulk_query () for the answers to appear
"""
def itemsetter (query):
""" Return a callable object that puts the answer into
the dictionary under the right key. """
def g (answer):
""" Put the answer into the dictionary. """
query_dict[query] = answer
# print "put: " + answer
return g
for query in query_dict.keys ():
if query:
self.query (query, itemsetter (query), rr)
def bulk_query (dict_, rr = adns.rr.A, timeout = 10):
""" Perform bulk lookup. """
a = AsyncDNS ()
a.bulk_query (dict_, rr)
a.wait (timeout)
a.cancel ()
if __name__ == '__main__':
import netaddr
queries = dict ()
for i in range (64, 64 + 32):
ip = '66.249.%d.42' % i # google assigned netblock
queries[ip] = None
bulk_query (queries, adns.rr.PTR)
ipset = netaddr.IPSet ()
for ip in sorted (queries):
if queries[ip] and 'proxy' in queries[ip][0]:
print (ip)
ipset.add (ip + '/24')
for cidr in ipset.iter_cidrs ():
print (cidr)

13
autocat3.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=autocat3 Service
After=network.target
[Service]
User=autocat
Type=simple
WorkingDirectory=/var/lib/autocat/autocat3
ExecStartPre=-/usr/bin/mkdir /var/run/autocat
ExecStart=/usr/local/bin/pipenv run python CherryPyApp.py
[Install]
WantedBy=multi-user.target

64
configuring.txt Normal file
View File

@ -0,0 +1,64 @@
sudo yum install git
#sudo yum install postgresql-server
#sudo yum install postgresql-contrib
# install py3 (might not be the bast way to do this)
#sudo yum install centos-release-scl
#sudo yum install rh-python36
#scl enable rh-python36 bash
#install pip
sudo yum groupinstall 'Development Tools'
# pip is not on secure_path
sudo /opt/rh/rh-python36/root/usr/bin/pip install --upgrade pip
sudo /opt/rh/rh-python36/root/usr/bin/pip install pipenv
# create autocat user with home directory /var/lib/autocat
sudo useradd -d /var/lib/ autocat
sudo passwd autocat
sudo su - autocat
# create ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub using app key from the gutenbergtools/autocat3 repo
# id_rsa should have permissions 400
mkdir .ssh
install -m 600 .ssh/id_rsa
touch .ssh/id_rsa.pub
#!! from local
# scp [local:]~.ssh/github [autocat@host:]~/.ssh/id_rsa
# scp [local:]~.ssh/github.pub [autocat@host:]~/.ssh/id_rsa.pub
chmod 400 .ssh/id_rsa
# create ~/.pgpass file to store password in format
# [pghost]:*:[pgdatabase]:[pguser]:[password]
chmod 400 .pgpass
#set default python - only needed if pu3 is
scl enable rh-python36 bash
echo 'source scl_source enable rh-python36' >> /var/lib/autocat/.bash_profile
git clone git@github.com:gutenbergtools/autocat3.git
cd autocat3
pipenv --three
git checkout remotes/origin/master
pipenv install
# add conf file
#!! from local
# scp [local:]~/autocat3.conf [autocat@host:]~/.autocat3
mkdir /var/lib/autocat/log/
touch /var/lib/autocat/log/error.log
touch /var/lib/autocat/log/access.log
exit
sudo mkdir /var/run/autocat
sudo touch /var/run/autocat/autocat3.pid
sudo chown autocat /var/run/autocat/autocat3.pid
sudo systemctl enable /var/lib/autocat/autocat3/autocat3.service
sudo systemctl start autocat3

321
ipinfo.py
View File

@ -1,321 +0,0 @@
#!/usr/bin/env python
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
"""
ipinfo.py
Copyright 2013-14 by Marcello Perathoner
Distributable under the GNU General Public License Version 3 or newer.
Find information about an IP, eg. hostname, whois, DNS blocklists.
The Spamhaus Block List (SBL) Advisory is a database of IP
addresses from which Spamhaus does not recommend the acceptance of
electronic mail.
The Spamhaus Exploits Block List (XBL) is a realtime database
of IP addresses of hijacked PCs infected by illegal 3rd party
exploits, including open proxies (HTTP, socks, AnalogX, wingate,
etc), worms/viruses with built-in spam engines, and other types of
trojan-horse exploits.
The Spamhaus PBL is a DNSBL database of end-user IP address
ranges which should not be delivering unauthenticated SMTP email
to any Internet mail server except those provided for specifically
by an ISP for that customer's use. The PBL helps networks enforce
their Acceptable Use Policy for dynamic and non-MTA customer IP
ranges.
"""
from __future__ import unicode_literals
import asyncdns
# pylint: disable=R0903
class DNSBL (object):
""" Base class for DNS blocklists. """
zone = ''
blackhat_tags = {}
dialup_tags = {}
### TOR ###
# see:
# https://www.torproject.org/projects/tordnsel.html.en
# https://www.dan.me.uk/dnsbl
class TorProject (DNSBL):
""" A TOR exitnode list. """
# note: reverse IP of www.gutenberg.org:80
zone = '80.47.134.19.152.ip-port.exitlist.torproject.org'
blackhat_tags = {
'127.0.0.2': 'TOR',
}
class TorDanme (DNSBL):
""" A TOR exitnode list. """
zone = 'torexit.dan.me.uk'
blackhat_tags = {
'127.0.0.100': 'TOR',
}
### SPAMHAUS ###
# see: http://www.spamhaus.org/faq/answers.lasso?section=DNSBL%20Usage#202
class Spamhaus (DNSBL):
""" A DNS blocklist. """
zone = 'zen.spamhaus.org'
blackhat_tags = {
'127.0.0.2': 'SPAMHAUS_SBL',
'127.0.0.3': 'SPAMHAUS_SBL_CSS',
'127.0.0.4': 'SPAMHAUS_XBL_CBL',
}
dialup_tags = {
'127.0.0.10': 'SPAMHAUS_PBL_ISP',
'127.0.0.11': 'SPAMHAUS_PBL',
}
lookup = 'http://www.spamhaus.org/query/ip/{ip}'
### SORBS ###
# see: http://www.sorbs.net/using.shtml
class SORBS (DNSBL):
""" A DNS blocklist. """
zone = 'dnsbl.sorbs.net'
blackhat_tags = {
'127.0.0.2': 'SORBS_HTTP_PROXY',
'127.0.0.3': 'SORBS_SOCKS_PROXY',
'127.0.0.4': 'SORBS_MISC_PROXY',
'127.0.0.5': 'SORBS_SMTP_RELAY',
'127.0.0.6': 'SORBS_SPAMMER',
'127.0.0.7': 'SORBS_WEB', # formmail etc.
'127.0.0.8': 'SORBS_BLOCK',
'127.0.0.9': 'SORBS_ZOMBIE',
'127.0.0.11': 'SORBS_BADCONF',
'127.0.0.12': 'SORBS_NOMAIL',
}
dialup_tags = {
'127.0.0.10': 'SORBS_DUL',
}
### mailspike.net ###
# see: http://mailspike.net/usage.html
class MailSpike (DNSBL):
""" A DNS blocklist. """
zone = 'bl.mailspike.net'
blackhat_tags = {
'127.0.0.2': 'MAILSPIKE_DISTRIBUTED_SPAM',
'127.0.0.10': 'MAILSPIKE_WORST_REPUTATION',
'127.0.0.11': 'MAILSPIKE_VERY_BAD_REPUTATION',
'127.0.0.12': 'MAILSPIKE_BAD_REPUTATION',
}
### shlink.org ###
# see: http://shlink.org/
class BlShlink (DNSBL):
""" A DNS blocklist. """
zone = 'bl.shlink.org'
blackhat_tags = {
'127.0.0.2': 'SHLINK_SPAM_SENDER',
'127.0.0.4': 'SHLINK_SPAM_ORIGINATOR',
'127.0.0.5': 'SHLINK_POLICY_BLOCK',
'127.0.0.6': 'SHLINK_ATTACKER',
}
class DynShlink (DNSBL):
""" A DNS dul list. """
zone = 'dyn.shlink.org'
dialup_tags = {
'127.0.0.3': 'SHLINK_DUL',
}
### barracudacentral.org ###
# see: http://www.barracudacentral.org/rbl/how-to-usee
class Barracuda (DNSBL):
""" A DNS blocklist. """
zone = 'b.barracudacentral.org'
blackhat_tags = {
'127.0.0.2': 'BARRACUDA_BLOCK',
}
### SHADOWSERVER ###
# http://www.shadowserver.org/wiki/pmwiki.php/Services/IP-BGP
class ShadowServer (DNSBL):
""" A DNS-based whois service. """
zone = 'origin.asn.shadowserver.org'
peer_zone = 'peer.asn.shadowserver.org'
fields = 'asn cidr org2 country org1 org'.split ()
# TEAMCYMRU
# http://www.team-cymru.org/Services/ip-to-asn.html
class TeamCymru (DNSBL):
""" A DNS-based whois service. """
zone = 'origin.asn.cymru.com'
asn_zone = 'asn.cymru.com'
fields = 'asn cidr country registry date'.split ()
class IPInfo (object):
""" Holds DNSBL information for one IP. """
dnsbl = [ Spamhaus, SORBS, MailSpike, BlShlink, DynShlink, Barracuda,
TorProject, TorDanme ]
""" Which blocklists to consider. """
def __init__ (self, aresolver, ip):
self.hostname = None
self.whois = {}
self.blackhat_tags = set ()
self.dialup_tags = set ()
ip = str (ip)
rr = asyncdns.adns.rr
try:
aresolver.query (ip, self._hostnamesetter (), rr.PTR)
for dnsbl in self.dnsbl:
aresolver.query_dnsbl (ip, dnsbl.zone, self._tagsetter (dnsbl))
# ShadowServer seems down: March 2014
aresolver.query_dnsbl (ip, ShadowServer.zone, self._whoissetter_ss (), rr.TXT)
# aresolver.query_dnsbl (ip, TeamCymru.zone, self._whoissetter_tc (aresolver), rr.TXT)
except:
pass
@property
def tags (self):
""" All tags (bad and dialup). """
return self.blackhat_tags | self.dialup_tags
def is_blackhat (self):
""" Return true if this is probably a blackhat IP. """
return bool (self.blackhat_tags)
def is_dialup (self):
""" Test if this IP is a dialup. """
return bool (self.dialup_tags)
def is_tor_exit (self):
""" Test if this is a Tor exit node. """
return 'TOR' in self.blackhat_tags
def _hostnamesetter (self):
""" Return a callable object that puts the answer into
the hostname attribute. """
def g (answer):
""" Store answer. """
self.hostname = answer[0]
return g
@staticmethod
def _filter (answers, tag_dict):
""" Lookup answers in tag_dict, return values of matches. """
return [ tag_dict[ip] for ip in answers if ip in tag_dict ]
def _tagsetter (self, dnsbl):
""" Return a callable object that puts the answer into
our *tags attributes. """
def g (answer):
""" Store answer. """
self.blackhat_tags.update (self._filter (answer, dnsbl.blackhat_tags))
self.dialup_tags.update (self._filter (answer, dnsbl.dialup_tags))
return g
@staticmethod
def _decode_txt (answer):
""" Helper: decode / unpack whois answer. """
try:
answer = answer[0][0].decode ('utf-8')
except UnicodeError:
answer = answer[0][0].decode ('iso-8859-1')
answer = answer.strip ('"').split ('|')
return [ a.strip () for a in answer if a ]
def _whoissetter_ss (self):
""" Return a callable object that puts the answer into
the whois dict. """
def g (answer):
""" Store answer. """
self.whois = dict (zip (ShadowServer.fields, self._decode_txt (answer)))
return g
def _whoissetter_tc (self, aresolver):
""" Return a callable object that puts the answer into
the right attribute. """
def g (answer):
""" Store answer. """
self.whois = dict (zip (TeamCymru.fields, self._decode_txt (answer)))
self.whois['org'] = None
# maybe there's still more info?
aresolver.query ('AS' + self.whois['asn'] + '.' + TeamCymru.asn_zone,
self._whoissetter_tc2 (), asyncdns.adns.rr.TXT)
return g
def _whoissetter_tc2 (self):
""" Return a callable object that puts the answer into
the right attribute. """
def g (answer):
""" Store answer. """
self.whois['org'] = self._decode_txt (answer)[-1]
return g
if __name__ == '__main__':
import sys
# test IP 127.0.0.2 should give all positives
a = asyncdns.AsyncDNS (asyncdns.RESOLV_CONF)
i = IPInfo (a, sys.argv[1])
a.wait ()
a.cancel ()
print ('hostname: %s' % i.hostname)
for k in sorted (i.whois.keys ()):
print ("%s: %s" % (k, i.whois[k]))
for tag in sorted (i.tags):
print (tag)
if i.is_blackhat ():
print ('BLACKHAT')
if i.is_dialup ():
print ('DUL')

View File

@ -123,7 +123,6 @@
<td rowspan="2" id="logo" i18n:comment="The PG logo at the top left of every page.">
<a href="/wiki/Main_Page" title="Go to the Main Page.">
<span id="${cherrypy.tools.rate_limiter.get_challenge ()}" class="icon icon_logo" />
</a>
</td>

View File

@ -56,7 +56,6 @@
<div class="table link">
<div class="row">
<div class="cell leftcell">
<div class="icon icon_search" id="${cherrypy.tools.rate_limiter.get_challenge ()}" />
</div>
<div class="cell content">
<form id="search" method="get" action="${os.mobile_search}"

View File

@ -1,165 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:py="http://genshi.edgewall.org/"
xmlns:i18n="http://genshi.edgewall.org/i18n"
xml:lang="en">
<!--! xml:lang avoids extraction for translation -->
<?python
from libgutenberg.GutenbergGlobals import xmlspecialchars as esc
?>
<py:def function="print_session">
<?python
from __future__ import unicode_literals
hostname = ''
whois = ''
tags = []
bad_tags = []
ips = d.ips
info = ips.ipinfo
if info is not None:
hostname = info.hostname
whois = ' - '.join (filter (None, info.whois.values ()))
if info.is_dialup ():
tags.append ('DUL')
bad_tags = sorted (info.tags & info.blackhat_tags)
if d['blocked'] == 9:
tags.append ('->DB')
if d['css_ok'] == False:
bad_tags.append ('NO_CSS')
session_cnt = len (d.sessions)
?>
<span class='ip'>${str (ips)}</span>
-
<span class='hits'>${d['hits']}</span> hits
<span py:if="d['dhits'] > 0"><span class='dhits'>${d['dhits']}</span> denied</span>
<span class='rhits'>(${d['rhits']}/${d['rhits_max']})</span>
<span py:if='session_cnt > 1' class='sessions'>${session_cnt} sess.</span>
<span class='host'>${hostname}</span>
<span class='tags'>${' '.join (sorted (tags))}</span>
<span class='bad_tags'>${' '.join (sorted (bad_tags))}</span>
<span class='whois'>${whois}</span>
<span class="ua">${' -- '.join (sorted (
[rl.ua_decode (ua) for ua in d['user_agents']]
))[:1000]}</span>
<span class="ua-sig">${' -- '.join (sorted (
[rl.ua_decode (sig) for sig in d['signatures']]
))[:1000]}</span>
<a href="/webmaster/stats/block/?ip=${ips.get_ip_to_block ()}">block</a>
<a href="/webmaster/stats/unblock/?ip=${ips.get_ip_to_block ()}">unblock</a>
</py:def>
<py:def function="print_requests">
<ul class="requests">
<li py:for="request in d['requests']">${request}</li>
</ul>
</py:def>
<head>
<title>AppServer Status</title>
<style type="text/css">
.ip { font-weight: bold }
.hits { font-weight: bold }
.dhits { font-weight: bold; color: red }
.rhits { color: blue }
.host { font-weight: bold }
.sessions { font-weight: bold; color: red }
.whois { color: grey }
.tags { font-weight: bold; color: green }
.bad_tags { font-weight: bold; color: red }
.ua { color: blue }
.ua-sig { color: #808 }
.requests { list-style-type: none; font-size: small; color: grey }
.requests li { display: inline }
.requests li:before { content: ' - ' }
.whitelisted { color: green }
.nagios { display: none }
</style>
</head>
<body>
<h1>Stats</h1>
<p>
RHits Max: ${rl.rhits_max}.
Captchas: ${rl.captchas_max}.
Cleanup Frequency: ${rl.frequency}s.
</p>
<p>Active Users: ${rl.users}</p>
<p>Hits: ${rl.hits}</p>
<p>Whitelisted: ${rl.whitelist_hits}</p>
<p>Denied: ${rl.denied_hits}</p>
<p>Blocked IPs: ${len (blocked)}</p>
<p>Total Backends: ${backends}</p>
<p>Active Backends: ${active_backends}</p>
<p>Formats Sum:</p>
<table>
<tr py:for="key, value, percent in bs.formats_sum_acc.iter_results ()">
<td>${key}</td><td>${value}</td><td>${"%.3f" % percent}</td>
<td class="nagios">nagios-${key}-sum: ${value} ${"%.3f" % percent}</td>
</tr>
</table>
<p>Formats Detail:</p>
<table>
<tr py:for="key, value, percent in bs.formats_acc.iter_results ()">
<td>${key}</td><td>${value}</td><td>${"%.3f" % percent}</td>
<td class="nagios">nagios-${key}: ${value} ${"%.3f" % percent}</td>
</tr>
</table>
<py:if test="resolve">
<p>Blocked IPs:</p>
<ul>
<!--! the blocked IPs sorted by IP -->
<li py:for="d in blocked">
${print_session ()}
${print_requests ()}
</li>
</ul>
<p>Busiest IPs:</p>
<ul>
<!--! the top 10 active IPs sorted by hits desc -->
<li py:for="d in busiest" class="${'whitelisted' if d.ips.whitelisted else ''}">
${print_session ()}
${print_requests ()}
</li>
</ul>
<p>IPs with most sessions:</p>
<ul>
<!--! the top 10 IPs with most sessions sorted by sessions desc -->
<li py:for="d in most_sessions" class="${'whitelisted' if d.ips.whitelisted else ''}">
${print_session ()}
${print_requests ()}
</li>
</ul>
<p>Active IPs: ${len (active)}</p>
<ul>
<!--! the active IPs sorted by IP -->
<li py:for="d in active" class="${'whitelisted' if d.ips.whitelisted else ''}">
${print_session ()}
</li>
</ul>
</py:if> <!--! resolve -->
</body>
</html>