├── .coveragerc ├── .gitignore ├── .travis.yml ├── COPYING ├── PRESUBMIT.py ├── README.md ├── adb_install_cert.py ├── certutils.py ├── certutils_test.py ├── codereview.settings ├── customhandlers.py ├── daemonserver.py ├── deterministic.js ├── dnsproxy.py ├── documentation ├── Contributing.md ├── GettingStarted.md ├── Rules.md └── WebPageReplayDiagram.png ├── exception_formatter.py ├── httparchive.py ├── httparchive_test.py ├── httpclient.py ├── httpclient_test.py ├── httpproxy.py ├── httpproxy_test.py ├── httpzlib.py ├── mock-archive.txt ├── mockhttprequest.py ├── net_configs.py ├── platformsettings.py ├── platformsettings_test.py ├── proxyshaper.py ├── proxyshaper_test.py ├── pylintrc ├── replay.py ├── replay_test.py ├── requirements.txt ├── rules ├── __init__.py ├── log_url.py └── rule.py ├── rules_parser.py ├── rules_parser_test.py ├── run_tests ├── script_injector.py ├── script_injector_test.py ├── servermanager.py ├── setup.py ├── sslproxy.py ├── sslproxy_test.py ├── test_runner.py ├── test_utils.py ├── third_party ├── __init__.py ├── dns │ ├── LICENSE │ ├── README.web-page-replay │ ├── __init__.py │ ├── dnssec.py │ ├── e164.py │ ├── edns.py │ ├── entropy.py │ ├── exception.py │ ├── flags.py │ ├── inet.py │ ├── ipv4.py │ ├── ipv6.py │ ├── message.py │ ├── name.py │ ├── namedict.py │ ├── node.py │ ├── opcode.py │ ├── query.py │ ├── rcode.py │ ├── rdata.py │ ├── rdataclass.py │ ├── rdataset.py │ ├── rdatatype.py │ ├── rdtypes │ │ ├── ANY │ │ │ ├── AFSDB.py │ │ │ ├── CERT.py │ │ │ ├── CNAME.py │ │ │ ├── DLV.py │ │ │ ├── DNAME.py │ │ │ ├── DNSKEY.py │ │ │ ├── DS.py │ │ │ ├── GPOS.py │ │ │ ├── HINFO.py │ │ │ ├── HIP.py │ │ │ ├── ISDN.py │ │ │ ├── KEY.py │ │ │ ├── LOC.py │ │ │ ├── MX.py │ │ │ ├── NS.py │ │ │ ├── NSEC.py │ │ │ ├── NSEC3.py │ │ │ ├── NSEC3PARAM.py │ │ │ ├── NXT.py │ │ │ ├── PTR.py │ │ │ ├── RP.py │ │ │ ├── RRSIG.py │ │ │ ├── RT.py │ │ │ ├── SIG.py │ │ │ ├── SOA.py │ │ │ ├── SPF.py │ │ │ ├── SSHFP.py │ │ │ ├── TXT.py │ │ │ ├── X25.py │ │ │ └── __init__.py │ │ ├── IN │ │ │ ├── A.py │ │ │ ├── AAAA.py │ │ │ ├── APL.py │ │ │ ├── DHCID.py │ │ │ ├── IPSECKEY.py │ │ │ ├── KX.py │ │ │ ├── NAPTR.py │ │ │ ├── NSAP.py │ │ │ ├── NSAP_PTR.py │ │ │ ├── PX.py │ │ │ ├── SRV.py │ │ │ ├── WKS.py │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── dsbase.py │ │ ├── keybase.py │ │ ├── mxbase.py │ │ ├── nsbase.py │ │ ├── sigbase.py │ │ └── txtbase.py │ ├── renderer.py │ ├── resolver.py │ ├── reversename.py │ ├── rrset.py │ ├── set.py │ ├── tokenizer.py │ ├── tsig.py │ ├── tsigkeyring.py │ ├── ttl.py │ ├── update.py │ ├── version.py │ └── zone.py ├── ipaddr │ ├── COPYING │ ├── MANIFEST.in │ ├── OWNERS │ ├── README │ ├── README.web-page-replay │ ├── ipaddr.py │ ├── ipaddr_test.py │ ├── setup.py │ └── test-2to3.sh ├── ipfw_win32 │ ├── LICENSE │ ├── README.txt │ ├── README.web-page-replay │ ├── ipfw.exe │ ├── ipfw.sys │ ├── netipfw.inf │ └── netipfw_m.inf └── jsmin │ ├── LICENSE.txt │ ├── MANIFEST.in │ ├── PKG-INFO │ ├── README.rst │ ├── README.web-page-replay │ └── __init__.py ├── trafficshaper.py ├── trafficshaper_test.py ├── util.py └── wpr_cert.pem /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | omit = 3 | */python?.?/* 4 | */third_party/* 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | language: python 16 | 17 | python: 18 | - "2.7" 19 | 20 | install: 21 | - pip install -r requirements.txt 22 | - pip install coveralls 23 | 24 | # traffic_shaper test requires sudo. 25 | sudo: required 26 | 27 | script: 28 | - sudo $(which coverage) run run_tests 29 | 30 | after_script: 31 | - coveralls 32 | 33 | notifications: 34 | email: false 35 | -------------------------------------------------------------------------------- /PRESUBMIT.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | """Presubmit script for changes affecting tools/perf/. 6 | 7 | See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts 8 | for more details about the presubmit API built into depot_tools. 9 | """ 10 | 11 | def _CommonChecks(input_api, output_api): 12 | """Performs common checks, which includes running pylint.""" 13 | results = [] 14 | results.extend(input_api.canned_checks.RunPylint( 15 | input_api, output_api, black_list=[], pylintrc='pylintrc')) 16 | return results 17 | 18 | 19 | def CheckChangeOnUpload(input_api, output_api): 20 | report = [] 21 | report.extend(_CommonChecks(input_api, output_api)) 22 | return report 23 | 24 | 25 | def CheckChangeOnCommit(input_api, output_api): 26 | report = [] 27 | report.extend(_CommonChecks(input_api, output_api)) 28 | return report 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build 2 | Status](https://travis-ci.org/chromium/web-page-replay.png)](https://travis-ci.org/chromium/web-page-replay) 3 | [![Coverage 4 | Status](https://coveralls.io/repos/chromium/web-page-replay/badge.svg)](https://coveralls.io/r/chromium/web-page-replay) 5 | 6 | # DEPRECATION NOTICE 7 | This tool is now deprecated & is replaced by 8 | [WebPageReplayGo](https://github.com/catapult-project/catapult/blob/master/web_page_replay_go/README.md) 9 | 10 | For the rationale, please see: https://bit.ly/wpr-go-project 11 | 12 | # Web Page Replay 13 | Record live Web pages and use them for local performance testing! 14 | 15 | ## How? 16 | Use local DNS and HTTP(S) proxies to captures your live traffic. Then 17 | use these captures in order to replay the same exact content, making 18 | sure that your tests get consistent results, that are not affected by 19 | the origin servers, the network, etc. 20 | 21 | ## Tell me more 22 | Check out the [getting 23 | started](documentation/GettingStarted.md) guide or take a 24 | look at the [architecture 25 | diagram](documentation/WebPageReplayDiagram.png). 26 | 27 | Also see [Note about web-page-replay 28 | code](https://docs.google.com/document/d/1cehHn3Lig7UYw_7pqQJjkbPTV3kS11EYwjKO-6jT0c8) 29 | 30 | ## I want to help 31 | If you find issues with the project, you can file issues on this repo. 32 | If you want to do more and contribute code to help the project evolve, 33 | check out our [contribution 34 | guidelines](documentation/Contributing.md). 35 | -------------------------------------------------------------------------------- /codereview.settings: -------------------------------------------------------------------------------- 1 | # This file is used by gcl to get repository specific information. 2 | CODE_REVIEW_SERVER: codereview.chromium.org 3 | PROJECT: web-page-replay 4 | -------------------------------------------------------------------------------- /daemonserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2010 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import threading 17 | 18 | 19 | class DaemonServer(object): 20 | """Base class which manages creation and cleanup of daemon style servers.""" 21 | 22 | def __enter__(self): 23 | # TODO: Because of python's Global Interpreter Lock (GIL), the threads 24 | # will run on the same CPU. Consider using processes instead because 25 | # the components do not need to communicate with each other. On Linux, 26 | # "taskset" could be used to assign each process to specific CPU/core. 27 | # Of course, only bother with this if the processing speed is an issue. 28 | # Some related discussion: http://stackoverflow.com/questions/990102/python- 29 | # global-interpreter-lock-gil-workaround-on-multi-core-systems-using-tasks 30 | thread = threading.Thread(target=self.serve_forever) 31 | thread.daemon = True # Python exits when no non-daemon threads are left. 32 | thread.start() 33 | return self 34 | 35 | def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb): 36 | self.cleanup() 37 | -------------------------------------------------------------------------------- /deterministic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function () { 4 | var random_count = 0; 5 | var random_count_threshold = 25; 6 | var random_seed = 0.462; 7 | Math.random = function() { 8 | random_count++; 9 | if (random_count > random_count_threshold){ 10 | random_seed += 0.1; 11 | random_count = 1; 12 | } 13 | return (random_seed % 1); 14 | }; 15 | if (typeof(crypto) == 'object' && 16 | typeof(crypto.getRandomValues) == 'function') { 17 | crypto.getRandomValues = function(arr) { 18 | var scale = Math.pow(256, arr.BYTES_PER_ELEMENT); 19 | for (var i = 0; i < arr.length; i++) { 20 | arr[i] = Math.floor(Math.random() * scale); 21 | } 22 | return arr; 23 | }; 24 | } 25 | })(); 26 | (function () { 27 | var date_count = 0; 28 | var date_count_threshold = 25; 29 | var orig_date = Date; 30 | // This should be replaced by web page replay by corresponding date 31 | // (usually the date when the recording was done) 32 | var time_seed = {{WPR_TIME_SEED_TIMESTAMP}}; 33 | Date = function() { 34 | if (this instanceof Date) { 35 | date_count++; 36 | if (date_count > date_count_threshold){ 37 | time_seed += 50; 38 | date_count = 1; 39 | } 40 | switch (arguments.length) { 41 | case 0: return new orig_date(time_seed); 42 | case 1: return new orig_date(arguments[0]); 43 | default: return new orig_date(arguments[0], arguments[1], 44 | arguments.length >= 3 ? arguments[2] : 1, 45 | arguments.length >= 4 ? arguments[3] : 0, 46 | arguments.length >= 5 ? arguments[4] : 0, 47 | arguments.length >= 6 ? arguments[5] : 0, 48 | arguments.length >= 7 ? arguments[6] : 0); 49 | } 50 | } 51 | return new Date().toString(); 52 | }; 53 | Date.__proto__ = orig_date; 54 | Date.prototype = orig_date.prototype; 55 | Date.prototype.constructor = Date; 56 | orig_date.now = function() { 57 | return new Date().getTime(); 58 | }; 59 | orig_date.prototype.getTimezoneOffset = function() { 60 | var dst2010Start = 1268560800000; 61 | var dst2010End = 1289120400000; 62 | if (this.getTime() >= dst2010Start && this.getTime() < dst2010End) 63 | return 420; 64 | return 480; 65 | }; 66 | })(); 67 | -------------------------------------------------------------------------------- /documentation/Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | 1. Thanks for considering contributing to Web Page Replay. You're awesome! 4 | 2. Style Guide - The source code of Web Page Replay follows the [Google 5 | Python Style 6 | Guide](http://google-styleguide.googlecode.com/svn/trunk/pyguide.html) so you should familiarize yourself with those 7 | guidelines. You may also wish to email web-page-replay-dev at 8 | googlegroups.com for advice on your change before starting. 9 | 3. Get the code - Fork this repo and clone it locally. 10 | 4. Get a review - All submissions, including submissions by project members, 11 | require review. 12 | 13 | ## Using rietveld 14 | 15 | 1. Make sure that you have a fork of the original repo. 16 | 2. Make your changes. 17 | 3. Commit your changes. 18 | 4. Run 'yes "" |git cl config' (first time only). 19 | 5. Run 'git cl upload'. 20 | 6. Once the review is approved, run 'git cl land' to land your changes. This also 21 | pushes your change to your forked branch. 22 | 7. Login your github account and make a pull request to merge the change from 23 | your forked branch to the original repo. 24 | 25 | ## The fine print 26 | 27 | Before we can use your code you have to sign the [Google Individual 28 | Contributor License 29 | Agreement](http://code.google.com/legal/individual-cla-v1.0.html), which you can do online. This is mainly 30 | because you own the copyright to your changes, even after your 31 | contribution becomes part of our codebase, so we need your permission to 32 | use and distribute your code. We also need to be sure of various other 33 | things, for instance that you'll tell us if you know that your code 34 | infringes on other people's patents. You don't have to do this until 35 | after you've submitted your code for review and a member has approved 36 | it, but you will have to do it before we can put your code into our 37 | codebase. 38 | 39 | Contributions made by corporations are covered by a different agreement 40 | than the one above, the [Software Grant and Corporate Contributor License 41 | Agreement](http://code.google.com/legal/corporate-cla-v1.0.html). 42 | -------------------------------------------------------------------------------- /documentation/GettingStarted.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | * A Mac running OS X 10.6 ("Snow Leopard") or Linux (tested with Ubuntu 3 | Lucid). Support for Windows is still experimental 4 | * [Python 2.6](http://www.python.org/download/releases/2.6.6/) 5 | 6 | # Install 7 | Only do this the first time. 8 | 9 | 1. Open the Terminal application and download the source. 10 | ``` 11 | $ git clone https://github.com/chromium/web-page-replay.git 12 | ``` 13 | 2. Move to the newly created directory. 14 | ``` 15 | $ cd web-page-replay 16 | ``` 17 | ## Network simulation 18 | For network simulation, you can use https://github.com/WPO-Foundation/tsproxy 19 | which works on most platforms. More realistic network simulation options can be 20 | achieved through using tools like dummynet, but those only support limited 21 | platforms. 22 | 23 | # Record 24 | First you must record the web page or pages that you wish to replay. 25 | 26 | 1. Open the web browser you wish to use and clear its cache so that all 27 | resources will be requested from the network. 28 | 2. Switch to the Terminal application and start the program in record mode. 29 | All HTTP requests performed on the machine while it is running will be 30 | saved into the archive. 31 | ``` 32 | $ sudo ./replay.py --record ~/archive.wpr 33 | ``` 34 | 3. Load the web page or pages in the open web browser. Be sure to wait 35 | until each is fully loaded. 36 | 4. Stop recording by killing the replay.py process with Ctrl+c. The archive 37 | will be saved to ~/archive.wpr. 38 | 39 | # Replay 40 | After you have created an archive, you may later replay it at any time. 41 | 42 | 1. Start the program in replay mode with a previously recorded archive. 43 | ``` 44 | $ sudo ./replay.py ~/archive.wpr 45 | ``` 46 | 2. Load recorded pages in a web browser. A 404 will be served for any pages 47 | or resources not in the recorded archive. 48 | 3. Stop replaying by killing the replay.py process with Ctrl+c. 49 | 50 | ## Network simulation examples 51 | During replay, you may simulate desired network conditions. This is 52 | useful for benchmarking. 53 | 54 | * 128KByte/s uplink bandwidth, 4Mbps/s downlink bandwidth with 100ms RTT 55 | time 56 | ``` 57 | $ sudo ./replay.py --up 128KByte/s --down 4Mbit/s --delay_ms=100 archive.wpr 58 | ``` 59 | * 1% packet loss rate 60 | ``` 61 | $ sudo ./replay.py --packet_loss_rate=0.01 ~/archive.wpr 62 | ``` 63 | 64 | ## Using browser proxy settings 65 | You may choose to disable the forwarding of DNS requests to the local 66 | replay server. If DNS request forwarding is disabled, an external 67 | mechanism must be used to forward traffic to the replay server. 68 | 69 | * Disable DNS forwarding 70 | ``` 71 | $ ./replay.py --no-dns_forwarding --record ~/archive.wpr 72 | ``` 73 | * Forwarding traffic to replay server (via Google Chrome on linux) 74 | 1. Go to Chrome Preferences -> Under the Hood -> Change Proxy Settings 75 | 2. Under Manual Proxy configuration -> HTTP proxy, enter 127.0.0.1 for IP 76 | and the port that web page replay is configured to listen to (default 77 | 80). 78 | 79 | Alternatively, traffic forwarding may also be configured via command 80 | line flags. 81 | ``` 82 | $ google-chrome --host-resolver-rules="MAP * 127.0.0.1:80,EXCLUDE localhost" 83 | ``` 84 | 85 | # HTTPS/SSL support 86 | By default, Web Page Replay, creates a self-signed certificate to serve 87 | SSL traffic. In order for it to work, browsers need to be configured to 88 | ignore certificate errors. Be aware that doing so opens a giant security 89 | hole. 90 | 91 | ``` 92 | $ google-chrome --ignore-certificate-errors 93 | ``` 94 | 95 | Firefox has [a configuration file for 96 | exceptions](https://developer.mozilla.org/En/Cert_override.txt). That requires listing 97 | each host that gets used. If you have a better solution, please add it 98 | to the comments below. IE and Safari options are also needed. 99 | 100 | To turn off SSL support, run replay.py with "--no-ssl". 101 | 102 | # Troubleshooting 103 | 104 | ## Permission errors 105 | 106 | On Linux, either of the following two errors are permission problems: 107 | 108 | ``` 109 | python: can't open file './replay.py': [Errno 13] Permission denied 110 | ``` 111 | ``` 112 | Traceback (most recent call last): 113 | File "./replay.py", line 50, in 114 | import dnsproxy 115 | File "/home/slamm/p/wpr/dnsproxy.py", line 19, in 116 | import platformsettings 117 | ImportError: No module named platformsettings 118 | ``` 119 | This can happen if you checkout the files to an NFS directory. Either 120 | move the files to a local directory, or make them world 121 | readable/executable. 122 | 123 | ## Unable to access auto mounted directories 124 | WPR can cause autofs to hang. On Ubuntu, the following command fixes it: 125 | 126 | ``` 127 | $ sudo restart autofs 128 | ``` 129 | 130 | # Help 131 | 132 | For full usage instructions and advanced options, see the program's 133 | help. 134 | 135 | ``` 136 | $ ./replay.py --help 137 | ``` 138 | -------------------------------------------------------------------------------- /documentation/Rules.md: -------------------------------------------------------------------------------- 1 | WebPageReplay Rule Language 2 | =========================== 3 | 4 | WebPageReplay rules allows developers to customize record/replay handling. 5 | 6 | Motiviation 7 | ----------- 8 | 9 | Web sites often require custom replay logic, e.g.: 10 | 11 | 1. The recording uploads various metrics/logs to: 12 | 13 | http://example.com/gen_204?emsg=foo 14 | 15 | but, during replay, it uploads different parameters: 16 | 17 | http://example.com/gen_204?emsg=bar 18 | 19 | so (as-is) our replay fails. We want "*/gen_204" to always respond 20 | "HTTP 204 No Change". 21 | 22 | 2. The recording fetches data from one server: 23 | 24 | http://mirrorA.example.com/stuff 25 | 26 | but replay selects a different server: 27 | 28 | http://mirrorB.example.com/stuff 29 | 30 | which breaks replay. We want "mirror*.example.com/stuff" to be equivalent. 31 | 32 | 3. The recorded URL + response contains a UID, e.g.: 33 | 34 | http://example.com?q=foo --> "you sent foo." 35 | 36 | but the replay asks for: 37 | 38 | http://example.com?q=bar --> replay error! 39 | 40 | We want it to reply "you sent bar." 41 | 42 | We could hack all the above rules into the code, but that can''t be (cleanly) extended or open sourced. 43 | 44 | Instead, we want a simple config file of "predicate --> action" rules. 45 | 46 | 47 | Format 48 | ------ 49 | 50 | The JSON-formatted rule file is specified on the command line: 51 | 52 | replay.py ... --rules_path my_rules ... 53 | 54 | The rules file must contain an array of single-item objects, e.g.: 55 | 56 | [{"comment": "ignore me"}, 57 | {"LogUrl": {"url": "example\\.com/logme.*"}}, 58 | {"LogUrl": {"url": "example\\.com/someotherpath"}} 59 | ] 60 | 61 | All "comment" items are ignored and support arbitrary values, e.g., a string 62 | or commented-out rule(s). 63 | 64 | All other items must specify a string TYPE key and object ARGS value, e.g.: 65 | 66 | {"LogUrl": {"url": "example\\.com/test", "stop": false}} 67 | 68 | The default TYPE package is "rules" and the default rule_parser 69 | "allowed_imports" is similarly restricted to only allow "rules" classes. 70 | 71 | The TYPE implementation class must match the Rule API defined in 72 | "rules/rule.py": 73 | 74 | class Rule(object): 75 | def IsType(self, rule_type_name): ... 76 | def ApplyRule(self, return_value, request, response): ... 77 | 78 | The ARGS must match the rule-specific constructor, e.g.: 79 | 80 | class LogUrl(rule.Rule): 81 | def __init__(self, url, stop=False): 82 | self._url_re = re.compile(url) 83 | self._stop = stop 84 | ... 85 | 86 | All rules of the same rule_type_name are chained together and applied in the 87 | same order as they appear in the input JSON file. 88 | 89 | 90 | Rules 91 | ------- 92 | 93 | ### rules.LogUrl: 94 | 95 | If the url pattern matches then log the request URL. 96 | -------------------------------------------------------------------------------- /documentation/WebPageReplayDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chromium/web-page-replay/472351e1122bb1beb936952c7e75ae58bf8a69f1/documentation/WebPageReplayDiagram.png -------------------------------------------------------------------------------- /exception_formatter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import math 16 | import os 17 | import sys 18 | import traceback 19 | 20 | 21 | def PrintFormattedException(msg=None): 22 | exception_class, exception, tb = sys.exc_info() 23 | 24 | def _GetFinalFrame(tb_level): 25 | while tb_level.tb_next: 26 | tb_level = tb_level.tb_next 27 | return tb_level.tb_frame 28 | 29 | processed_tb = traceback.extract_tb(tb) 30 | frame = _GetFinalFrame(tb) 31 | exception_list = traceback.format_exception_only(exception_class, exception) 32 | exception_string = '\n'.join(l.strip() for l in exception_list) 33 | 34 | if msg: 35 | print >> sys.stderr 36 | print >> sys.stderr, msg 37 | 38 | _PrintFormattedTrace(processed_tb, frame, exception_string) 39 | 40 | def PrintFormattedFrame(frame, exception_string=None): 41 | _PrintFormattedTrace(traceback.extract_stack(frame), frame, exception_string) 42 | 43 | 44 | def _PrintFormattedTrace(processed_tb, frame, exception_string=None): 45 | """Prints an Exception in a more useful format than the default. 46 | """ 47 | print >> sys.stderr 48 | 49 | # Format the traceback. 50 | base_dir = os.path.dirname(__file__) 51 | print >> sys.stderr, 'Traceback (most recent call last):' 52 | for filename, line, function, text in processed_tb: 53 | filename = os.path.abspath(filename) 54 | if filename.startswith(base_dir): 55 | filename = filename[len(base_dir)+1:] 56 | print >> sys.stderr, ' %s at %s:%d' % (function, filename, line) 57 | print >> sys.stderr, ' %s' % text 58 | 59 | # Format the exception. 60 | if exception_string: 61 | print >> sys.stderr, exception_string 62 | 63 | # Format the locals. 64 | local_variables = [(variable, value) for variable, value in 65 | frame.f_locals.iteritems() if variable != 'self'] 66 | print >> sys.stderr 67 | print >> sys.stderr, 'Locals:' 68 | if local_variables: 69 | longest_variable = max(len(v) for v, _ in local_variables) 70 | for variable, value in sorted(local_variables): 71 | value = repr(value) 72 | possibly_truncated_value = _AbbreviateMiddleOfString(value, ' ... ', 1024) 73 | truncation_indication = '' 74 | if len(possibly_truncated_value) != len(value): 75 | truncation_indication = ' (truncated)' 76 | print >> sys.stderr, ' %s: %s%s' % (variable.ljust(longest_variable + 1), 77 | possibly_truncated_value, 78 | truncation_indication) 79 | else: 80 | print >> sys.stderr, ' No locals!' 81 | 82 | print >> sys.stderr 83 | sys.stderr.flush() 84 | 85 | 86 | def _AbbreviateMiddleOfString(target, middle, max_length): 87 | if max_length < 0: 88 | raise ValueError('Must provide positive max_length') 89 | if len(middle) > max_length: 90 | raise ValueError('middle must not be greater than max_length') 91 | 92 | if len(target) <= max_length: 93 | return target 94 | half_length = (max_length - len(middle)) / 2. 95 | return (target[:int(math.floor(half_length))] + middle + 96 | target[-int(math.ceil(half_length)):]) 97 | -------------------------------------------------------------------------------- /httpzlib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2011 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | """Apply gzip/deflate to separate chunks of data.""" 17 | 18 | import struct 19 | import zlib 20 | 21 | GZIP_HEADER = ( 22 | '\037\213' # magic header 23 | '\010' # compression method 24 | '\000' # flags (none) 25 | '\000\000\000\000' # packed time (use zero) 26 | '\002' 27 | '\377') 28 | 29 | 30 | def compress_chunks(uncompressed_chunks, use_gzip): 31 | """Compress a list of data with gzip or deflate. 32 | 33 | The returned chunks may be used with HTTP chunked encoding. 34 | 35 | Args: 36 | uncompressed_chunks: a list of strings 37 | (e.g. ["this is the first chunk", "and the second"]) 38 | use_gzip: if True, compress with gzip. Otherwise, use deflate. 39 | 40 | Returns: 41 | [compressed_chunk_1, compressed_chunk_2, ...] 42 | """ 43 | if use_gzip: 44 | size = 0 45 | crc = zlib.crc32("") & 0xffffffffL 46 | compressor = zlib.compressobj( 47 | 6, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) 48 | else: 49 | compressor = zlib.compressobj() 50 | compressed_chunks = [] 51 | last_index = len(uncompressed_chunks) - 1 52 | for index, data in enumerate(uncompressed_chunks): 53 | chunk = '' 54 | if use_gzip: 55 | size += len(data) 56 | crc = zlib.crc32(data, crc) & 0xffffffffL 57 | if index == 0: 58 | chunk += GZIP_HEADER 59 | chunk += compressor.compress(data) 60 | if index < last_index: 61 | chunk += compressor.flush(zlib.Z_SYNC_FLUSH) 62 | else: 63 | chunk += (compressor.flush(zlib.Z_FULL_FLUSH) + 64 | compressor.flush()) 65 | if use_gzip: 66 | chunk += (struct.pack(" 0: 88 | logging.debug('read sleep: %0.4fs %d requests)', wait, num_requests) 89 | time.sleep(wait) 90 | return data 91 | 92 | def readline(self, size=-1): 93 | return self._read(self.original_file.readline, size) 94 | 95 | def read(self, size=-1): 96 | return self._read(self.original_file.read, size) 97 | 98 | def __getattr__(self, name): 99 | """Forward any non-overriden calls.""" 100 | return getattr(self.original_file, name) 101 | 102 | 103 | def GetBitsPerSecond(bandwidth): 104 | """Return bits per second represented by dummynet bandwidth option. 105 | 106 | See ipfw/dummynet.c:read_bandwidth for how it is really done. 107 | 108 | Args: 109 | bandwidth: a dummynet-style bandwidth specification (e.g. "10Kbit/s") 110 | """ 111 | if bandwidth == '0': 112 | return 0 113 | bw_re = r'^(\d+)(?:([KM])?(bit|Byte)/s)?$' 114 | match = re.match(bw_re, str(bandwidth)) 115 | if not match: 116 | raise BandwidthValueError('Value, "%s", does not match regex: %s' % ( 117 | bandwidth, bw_re)) 118 | bw = int(match.group(1)) 119 | if match.group(2) == 'K': 120 | bw *= 1000 121 | if match.group(2) == 'M': 122 | bw *= 1000000 123 | if match.group(3) == 'Byte': 124 | bw *= 8 125 | return bw 126 | -------------------------------------------------------------------------------- /pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | 3 | # Disable the message, report, category or checker with the given id(s). 4 | # TODO(wpr-owners): Reduce this list to as small as possible. 5 | disable=I0010,I0011,abstract-class-little-used,abstract-class-not-used,anomalous-backslash-in-string,bad-builtin,bad-context-manager,bad-continuation,bad-str-strip-call,broad-except,cell-var-from-loop,deprecated-lambda,deprecated-module,duplicate-code,eval-used,exec-used,fixme,function-redefined,global-statement,interface-not-implemented,invalid-name,locally-enabled,logging-not-lazy,missing-docstring,missing-final-newline,no-init,no-member,no-name-in-module,no-self-use,no-self-use,not-callable,star-args,too-few-public-methods,too-many-ancestors,too-many-arguments,too-many-branches,too-many-function-args,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,useless-else-on-loop,unused-variable,attribute-defined-outside-init,protected-access 6 | 7 | 8 | [REPORTS] 9 | 10 | # Don't write out full reports, just messages. 11 | reports=no 12 | 13 | 14 | [FORMAT] 15 | 16 | # We use two spaces for indents, instead of the usual four spaces or tab. 17 | indent-string=' ' 18 | -------------------------------------------------------------------------------- /replay_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2012 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | """Unit tests for replay. 17 | 18 | Usage: 19 | $ ./replay_test.py 20 | """ 21 | 22 | import replay 23 | import unittest 24 | 25 | 26 | class MockOptions(dict): 27 | """A dict with items that can be accessed as attributes.""" 28 | def __getattr__(self, name): 29 | return self[name] 30 | 31 | 32 | class OptionsWrapperTest(unittest.TestCase): 33 | 34 | def testNoTrafficShapingByDefault(self): 35 | parser = replay.GetParser() 36 | options = parser.parse_args([]) 37 | options = replay.OptionsWrapper(options, parser) 38 | self.assertEqual({}, options.shaping_dns) 39 | self.assertEqual({}, options.shaping_http) 40 | self.assertEqual({}, options.shaping_dummynet) 41 | 42 | def testShapingProxyWithoutOptionsGivesEmptySettings(self): 43 | parser = replay.GetParser() 44 | options = parser.parse_args(['--shaping=proxy']) 45 | options = replay.OptionsWrapper(options, parser) 46 | self.assertEqual({}, options.shaping_dns) 47 | self.assertEqual({}, options.shaping_http) 48 | self.assertEqual({}, options.shaping_dummynet) 49 | 50 | def testShapingProxyWithNetOption(self): 51 | parser = replay.GetParser() 52 | options = parser.parse_args(['--shaping=proxy', '--net=cable']) 53 | options = replay.OptionsWrapper(options, parser) 54 | expected_http = { 55 | 'down_bandwidth': '5Mbit/s', 'delay_ms': '28', 'up_bandwidth': '1Mbit/s' 56 | } 57 | self.assertEqual({'delay_ms': '28'}, options.shaping_dns) 58 | self.assertEqual(expected_http, options.shaping_http) 59 | self.assertEqual({}, options.shaping_dummynet) 60 | 61 | def testNetOptionUsesDummynetByDefault(self): 62 | parser = replay.GetParser() 63 | options = parser.parse_args(['--net=cable']) 64 | options = replay.OptionsWrapper(options, parser) 65 | expected_dummynet = { 66 | 'down_bandwidth': '5Mbit/s', 'delay_ms': '28', 'up_bandwidth': '1Mbit/s' 67 | } 68 | self.assertEqual({}, options.shaping_dns) 69 | self.assertEqual({}, options.shaping_http) 70 | self.assertEqual(expected_dummynet, options.shaping_dummynet) 71 | 72 | def testPacketLossForDummynet(self): 73 | parser = replay.GetParser() 74 | options = parser.parse_args(['--packet_loss_rate=12']) 75 | options = replay.OptionsWrapper(options, parser) 76 | self.assertEqual({'packet_loss_rate': '12'}, options.shaping_dummynet) 77 | 78 | def testIgnoredProxyShapingOptions(self): 79 | parser = replay.GetParser() 80 | options = parser.parse_args( 81 | ['--packet_loss_rate=12', '--init_cwnd=10', '--shaping=proxy']) 82 | options = replay.OptionsWrapper(options, parser) 83 | self.assertEqual({}, options.shaping_dns) 84 | self.assertEqual({}, options.shaping_http) 85 | self.assertEqual({}, options.shaping_dummynet) 86 | 87 | 88 | if __name__ == '__main__': 89 | unittest.main() 90 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyOpenSSL==0.13 2 | -------------------------------------------------------------------------------- /rules/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | # Export rules for rules_parser access. 18 | from rules.log_url import LogUrl 19 | -------------------------------------------------------------------------------- /rules/log_url.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import logging 17 | import re 18 | 19 | from rules import rule 20 | 21 | 22 | class LogUrl(rule.Rule): 23 | """Logs the request URL.""" 24 | 25 | def __init__(self, url, stop=False): 26 | r"""Initializes with a url pattern. 27 | 28 | Args: 29 | url: a string regex, e.g. r'example\.com/id=(\d{6})'. 30 | stop: boolean ApplyRule should_stop value, defaults to True. 31 | """ 32 | self._url_re = re.compile(url) 33 | self._stop = stop 34 | 35 | def IsType(self, rule_type_name): 36 | """Returns True if the name matches this rule.""" 37 | return rule_type_name == 'log_url' 38 | 39 | def ApplyRule(self, return_value, request, response): 40 | """Returns True if logged. 41 | 42 | Args: 43 | return_value: the prior log_url rule's return_value (if any). 44 | request: the httparchive ArchivedHttpRequest. 45 | response: the httparchive ArchivedHttpResponse. 46 | Returns: 47 | A (should_stop, return_value) tuple, e.g. (False, True). 48 | """ 49 | del response # unused. 50 | url = '%s%s' % (request.host, request.full_path) 51 | if not self._url_re.match(url): 52 | return False, return_value 53 | 54 | logging.debug('url: %s', url) 55 | return self._stop, True 56 | 57 | def __str__(self): 58 | return _ToString(self, ('url', self._url_re.pattern), 59 | None if self._stop else ('stop', False)) 60 | 61 | def __repr__(self): 62 | return str(self) 63 | 64 | 65 | def _ToString(obj, *items): 66 | pkg = (obj.__module__[:obj.__module__.rfind('.') + 1] 67 | if '.' in obj.__module__ else '') 68 | clname = obj.__class__.__name__ 69 | args = [('%s=r\'%s\'' % item if isinstance(item[1], basestring) 70 | else '%s=%s' % item) for item in items if item] 71 | return '%s%s(%s)' % (pkg, clname, ', '.join(args)) 72 | -------------------------------------------------------------------------------- /rules/rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2015 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | class Rule(object): 18 | """An optional base class for rule implementations. 19 | 20 | The rule_parser looks for the 'IsType' and 'ApplyRule' methods by name, so 21 | rules are not strictly required to extend this class. 22 | """ 23 | 24 | def IsType(self, rule_type_name): 25 | """Returns True if the name matches this rule.""" 26 | raise NotImplementedError 27 | 28 | def ApplyRule(self, return_value, request, response): 29 | """Invokes this rule with the given args. 30 | 31 | Args: 32 | return_value: the prior rule's return_value (if any). 33 | request: the httparchive ArchivedHttpRequest. 34 | response: the httparchive ArchivedHttpResponse, which may be None. 35 | Returns: 36 | A (should_stop, return_value) tuple. Typically the request and response 37 | are treated as immutable, so it's the caller's job to apply the 38 | return_value (e.g., set response fields). 39 | """ 40 | raise NotImplementedError 41 | -------------------------------------------------------------------------------- /rules_parser_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Unit tests for rules_parser. Usage: ./rules_parser_test.py""" 16 | 17 | import collections 18 | import logging 19 | from StringIO import StringIO 20 | import unittest 21 | 22 | import rules_parser 23 | 24 | 25 | class RuleParserTest(unittest.TestCase): 26 | 27 | @classmethod 28 | def setUpClass(cls): 29 | if not logging.root.handlers: 30 | logging.basicConfig(level=logging.DEBUG, # Enable log_url stdout. 31 | format='%(asctime)s %(levelname)s %(message)s') 32 | 33 | def testCall(self): 34 | my_rules = rules_parser.Rules(StringIO(r''' 35 | [{"comment": "ignore me"}, 36 | {"LogUrl": {"url": "example\\.com/ss.*"}}, 37 | {"LogUrl": {"url": "example\\.com/blah$"}}]''')) 38 | log_url = my_rules.Find('log_url') 39 | self.assertEquals(True, log_url(FakeRequest(full_path='/ss'), None)) 40 | self.assertEquals(True, log_url(FakeRequest(full_path='/ssxxxx'), None)) 41 | self.assertEquals(True, log_url(FakeRequest(full_path='/blah'), None)) 42 | self.assertEquals(None, log_url(FakeRequest(full_path='/blahxxx'), None)) 43 | self.assertEquals(None, log_url(FakeRequest(full_path='/'), None)) 44 | 45 | def testImport(self): 46 | my_rules = rules_parser.Rules(StringIO(r''' 47 | [{"rules.LogUrl": {"url": "example\\.com/ss.*"}}]''')) 48 | self.assertTrue(my_rules.Contains('log_url')) 49 | 50 | def testRaises(self): 51 | input_pairs = [ 52 | 'bad_json', 53 | '123', 54 | '{}', 55 | '[42]', 56 | '[{12:34}]', 57 | '[{"a":"b","c":"d"}]', 58 | '[{"bad+rule@name":{}}]', 59 | '["unallowed.Path":{}]', 60 | '["NoSuchRule":{}]', 61 | '["LogUrl":"bad"]', 62 | '["LogUrl":{}]', 63 | '["LogUrl":{"url":123}]', 64 | '["LogUrl":{"url":"", "bad_arg":123}]', 65 | ] 66 | for input_text in input_pairs: 67 | self.assertRaises(Exception, rules_parser.Rules, StringIO(input_text)) 68 | 69 | 70 | class FakeRequest(collections.namedtuple( 71 | 'FakeRequest', ('command', 'host', 'full_path', 'request_body', 72 | 'headers', 'is_ssl'))): 73 | 74 | def __new__(cls, command='GET', host='example.com', full_path='/', 75 | request_body=None, headers=None, is_ssl=False): 76 | return super(FakeRequest, cls).__new__( 77 | cls, command, host, full_path, request_body, headers or {}, is_ssl) 78 | 79 | 80 | if __name__ == '__main__': 81 | unittest.main() 82 | -------------------------------------------------------------------------------- /run_tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | import test_runner 6 | 7 | _WPR_DIR = os.path.dirname(os.path.abspath(__file__)) 8 | 9 | if __name__ == '__main__': 10 | runner = test_runner.TestRunner() 11 | runner.AddDirectory(_WPR_DIR) 12 | sys.exit(runner.Main()) 13 | -------------------------------------------------------------------------------- /script_injector.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2013 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | """Inject javascript into html page source code.""" 17 | 18 | import datetime 19 | import logging 20 | import os 21 | import re 22 | import util 23 | import third_party.jsmin as jsmin 24 | 25 | DOCTYPE_RE = re.compile(r'^.{,256}?()?.{,256}?', 26 | re.IGNORECASE | re.DOTALL) 27 | HTML_RE = re.compile(r'^.{,256}?()?.{,256}?', 28 | re.IGNORECASE | re.DOTALL) 29 | HEAD_RE = re.compile(r'^.{,256}?()?.{,256}?', 30 | re.IGNORECASE | re.DOTALL) 31 | 32 | # Occurences of this marker in injected scripts will be replaced with 33 | # recording time in javascripts' Date().toValue() format. This allows 34 | # to properly set deterministic date in JS code. See 35 | # https://github.com/chromium/web-page-replay/issues/71 for details. 36 | TIME_SEED_MARKER = '{{WPR_TIME_SEED_TIMESTAMP}}' 37 | 38 | 39 | def GetScriptInjector(scripts): 40 | """Loads |scripts| from disk and returns an injector of their content.""" 41 | lines = [] 42 | if scripts: 43 | if not isinstance(scripts, list): 44 | scripts = scripts.split(',') 45 | for script in scripts: 46 | if os.path.exists(script): 47 | with open(script) as f: 48 | lines.extend(f.read()) 49 | elif util.resource_exists(script): 50 | lines.extend(util.resource_string(script)) 51 | else: 52 | raise Exception('Script does not exist: %s', script) 53 | 54 | script_template = jsmin.jsmin(''.join(lines), quote_chars="'\"`") 55 | def injector(record_time): 56 | delta = record_time - datetime.datetime(1970, 1, 1) 57 | js_timestamp = \ 58 | int(delta.total_seconds()) * 1000 + delta.microseconds / 1000 59 | return script_template.replace(TIME_SEED_MARKER, str(js_timestamp)) 60 | return injector 61 | 62 | 63 | def _IsHtmlContent(content): 64 | content = content.strip() 65 | return content.startswith('<') and content.endswith('>') 66 | 67 | 68 | def InjectScript(text_chunks, content_type, script_to_inject): 69 | """Inject |script_to_inject| into |content| if |content_type| is 'text/html'. 70 | 71 | Inject |script_to_inject| into |text_chunks| immediately after , 72 | or , if one of them is found. Otherwise, inject at 73 | the beginning. 74 | 75 | Returns: 76 | text_chunks, already_injected 77 | |text_chunks| is the new content if script is injected, otherwise 78 | the original. If the script was injected, exactly one chunk in 79 | |text_chunks| will have changed. 80 | |just_injected| indicates if |script_to_inject| was just injected in 81 | the content. 82 | """ 83 | if not content_type or content_type != 'text/html': 84 | return text_chunks, False 85 | content = "".join(text_chunks) 86 | if not content or not _IsHtmlContent(content) or script_to_inject in content: 87 | return text_chunks, False 88 | for regexp in (HEAD_RE, HTML_RE, DOCTYPE_RE): 89 | matchobj = regexp.search(content) 90 | if matchobj: 91 | pos = matchobj.end(0) 92 | for i, chunk in enumerate(text_chunks): 93 | if pos <= len(chunk): 94 | result = text_chunks[:] 95 | result[i] = '%s%s' % (chunk[0:pos], 96 | script_to_inject, 97 | chunk[pos:]) 98 | return result, True 99 | pos -= len(chunk) 100 | result = text_chunks[:] 101 | result[0] = '%s' % (script_to_inject, 102 | text_chunks[0]) 103 | logging.warning('Inject at the very beginning, because no tag of ' 104 | ', or is found.') 105 | return result, True 106 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2012 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | """Creates a distributable python package. 17 | 18 | Creating new packages: 19 | 1. Generate the package, dist/webpagereplay-X.X.tar.gz: 20 | python setup.py sdist 21 | 2. Upload the package file to the following: 22 | http://code.google.com/p/web-page-replay/downloads/entry 23 | 24 | Installing packages: 25 | $ easy_install http://web-page-replay.googlecode.com/files/webpagereplay-X.X.tar.gz 26 | - The replay and httparchive commands are now on your PATH. 27 | """ 28 | 29 | import setuptools 30 | 31 | setuptools.setup( 32 | name='webpagereplay', 33 | version='1.1.2', 34 | description='Record and replay web content', 35 | author='Web Page Replay Project Authors', 36 | author_email='web-page-replay-dev@googlegroups.com', 37 | url='http://code.google.com/p/web-page-replay/', 38 | license='Apache License 2.0', 39 | install_requires=['dnspython>=1.8'], 40 | packages=[ 41 | '', 42 | 'third_party', 43 | 'third_party.ipaddr' 44 | ], 45 | package_dir={'': '.'}, 46 | package_data={ 47 | '': ['*.js', '*.txt', 'COPYING', 'LICENSE'], 48 | }, 49 | entry_points={ 50 | 'console_scripts': [ 51 | 'httparchive = httparchive:main', 52 | 'replay = replay:main', 53 | ] 54 | }, 55 | ) 56 | -------------------------------------------------------------------------------- /sslproxy.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Extends BaseHTTPRequestHandler with SSL certificate generation.""" 16 | 17 | import logging 18 | import socket 19 | 20 | import certutils 21 | 22 | 23 | 24 | def _SetUpUsingDummyCert(handler): 25 | """Sets up connection providing the certificate to the client. 26 | 27 | This method handles Server Name Indication (SNI) using dummy certs. 28 | 29 | Args: 30 | handler: an instance of BaseHTTPServer.BaseHTTPRequestHandler that is used 31 | by some instance of BaseHTTPServer.HTTPServer. 32 | """ 33 | # One of: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or TLSv1_METHOD 34 | context = certutils.get_ssl_context() 35 | def handle_servername(connection): 36 | """A SNI callback that happens during do_handshake().""" 37 | try: 38 | host = connection.get_servername() 39 | if host: 40 | cert_str = ( 41 | handler.server.get_certificate(host)) 42 | new_context = certutils.get_ssl_context() 43 | cert = certutils.load_cert(cert_str) 44 | new_context.use_certificate(cert) 45 | new_context.use_privatekey_file(handler.server.ca_cert_path) 46 | connection.set_context(new_context) 47 | return new_context 48 | # else: fail with 'no shared cipher' 49 | except Exception, e: 50 | # Do not leak any exceptions or else openssl crashes. 51 | logging.error('Exception in SNI handler: %s', e) 52 | 53 | context.set_tlsext_servername_callback(handle_servername) 54 | handler.connection = certutils.get_ssl_connection(context, handler.connection) 55 | handler.connection.set_accept_state() 56 | try: 57 | handler.connection.do_handshake() 58 | except certutils.Error, v: 59 | host = handler.connection.get_servername() 60 | if not host: 61 | logging.error('Dropping request without SNI') 62 | return '' 63 | raise certutils.Error('SSL handshake error %s: %s' % (host, str(v))) 64 | 65 | # Re-wrap the read/write streams with our new connection. 66 | handler.rfile = socket._fileobject(handler.connection, 'rb', handler.rbufsize, 67 | close=False) 68 | handler.wfile = socket._fileobject(handler.connection, 'wb', handler.wbufsize, 69 | close=False) 70 | 71 | 72 | def wrap_handler(handler_class): 73 | """Wraps a BaseHTTPHandler with SSL MITM certificates.""" 74 | if certutils.openssl_import_error: 75 | # pylint: disable=raising-bad-type 76 | raise certutils.openssl_import_error 77 | 78 | class WrappedHandler(handler_class): 79 | 80 | def setup(self): 81 | handler_class.setup(self) 82 | _SetUpUsingDummyCert(self) 83 | 84 | def finish(self): 85 | handler_class.finish(self) 86 | self.connection.shutdown() 87 | self.connection.close() 88 | 89 | return WrappedHandler 90 | -------------------------------------------------------------------------------- /test_runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | import unittest 6 | import sys 7 | import os 8 | import optparse 9 | 10 | __all__ = [] 11 | 12 | def FilterSuite(suite, predicate): 13 | new_suite = suite.__class__() 14 | 15 | for x in suite: 16 | if isinstance(x, unittest.TestSuite): 17 | subsuite = FilterSuite(x, predicate) 18 | if subsuite.countTestCases() == 0: 19 | continue 20 | 21 | new_suite.addTest(subsuite) 22 | continue 23 | 24 | assert isinstance(x, unittest.TestCase) 25 | if predicate(x): 26 | new_suite.addTest(x) 27 | 28 | return new_suite 29 | 30 | class _TestLoader(unittest.TestLoader): 31 | def __init__(self, *args): 32 | super(_TestLoader, self).__init__(*args) 33 | self.discover_calls = [] 34 | 35 | def loadTestsFromModule(self, module, use_load_tests=True): 36 | if module.__file__ != __file__: 37 | return super(_TestLoader, self).loadTestsFromModule( 38 | module, use_load_tests) 39 | 40 | suite = unittest.TestSuite() 41 | for discover_args in self.discover_calls: 42 | subsuite = self.discover(*discover_args) 43 | suite.addTest(subsuite) 44 | return suite 45 | 46 | class _RunnerImpl(unittest.TextTestRunner): 47 | def __init__(self, filters): 48 | super(_RunnerImpl, self).__init__(verbosity=2) 49 | self.filters = filters 50 | 51 | def ShouldTestRun(self, test): 52 | return not self.filters or any(name in test.id() for name in self.filters) 53 | 54 | def run(self, suite): 55 | filtered_test = FilterSuite(suite, self.ShouldTestRun) 56 | return super(_RunnerImpl, self).run(filtered_test) 57 | 58 | 59 | class TestRunner(object): 60 | def __init__(self): 61 | self._loader = _TestLoader() 62 | 63 | def AddDirectory(self, dir_path, test_file_pattern="*test.py"): 64 | assert os.path.isdir(dir_path) 65 | 66 | self._loader.discover_calls.append((dir_path, test_file_pattern, dir_path)) 67 | 68 | def Main(self, argv=None): 69 | if argv is None: 70 | argv = sys.argv 71 | 72 | parser = optparse.OptionParser() 73 | options, args = parser.parse_args(argv[1:]) 74 | 75 | runner = _RunnerImpl(filters=args) 76 | return unittest.main(module=__name__, argv=[sys.argv[0]], 77 | testLoader=self._loader, 78 | testRunner=runner) 79 | -------------------------------------------------------------------------------- /test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2016 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import unittest 17 | import urllib2 18 | 19 | 20 | def _IsInternetOn(): 21 | try: 22 | urllib2.urlopen('https://example.com', timeout=10) 23 | return True 24 | except urllib2.URLError as err: 25 | return False 26 | 27 | 28 | class RealNetworkFetchTest(unittest.TestCase): 29 | def setUp(self): 30 | if not _IsInternetOn(): 31 | self.skipTest('No internet, skip test') 32 | -------------------------------------------------------------------------------- /third_party/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2010 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | try: 19 | __file__ 20 | except NameError: 21 | __file__ = sys.argv[0] 22 | third_party_dir = os.path.dirname(os.path.abspath(__file__)) 23 | ipaddr_dir = os.path.join(third_party_dir, "ipaddr") 24 | sys.path.append(ipaddr_dir) # workaround for no __init__.py 25 | import ipaddr 26 | 27 | # Modules in dns/ import sibling modules by "import dns/xxx", but 28 | # some platform has dns/ in global site-packages directory so we need to raise 29 | # the precedence of local search path (crbug/493869). 30 | # The implementation here preloads all dns/ modules into this package so clients 31 | # don't need to worry about import path issue. 32 | # An easier solution might be modify dns/ modules to use relative path, but I 33 | # tried not to touch third_party lib for now. 34 | sys.path.insert(0, third_party_dir) 35 | from dns import __all__ as all_dns_modules 36 | all_dns_modules = ['dns.' + m for m in all_dns_modules] 37 | map(__import__, all_dns_modules) 38 | sys.path.pop(0) 39 | -------------------------------------------------------------------------------- /third_party/dns/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2001-2003 Nominum, Inc. 2 | 3 | Permission to use, copy, modify, and distribute this software and its 4 | documentation for any purpose with or without fee is hereby granted, 5 | provided that the above copyright notice and this permission notice 6 | appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /third_party/dns/README.web-page-replay: -------------------------------------------------------------------------------- 1 | Name: A DNS toolkit for Python 2 | Short Name: dnspython 3 | URL: http://www.dnspython.org/ 4 | Version: 1.8.0 (found in ./version.py) 5 | License: ISC 6 | License File: LICENSE 7 | 8 | Description: 9 | Used by Web Page Replay's dnsproxy module to create and handle dns queries. 10 | 11 | Local Modifications: 12 | None. -------------------------------------------------------------------------------- /third_party/dns/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """dnspython DNS toolkit""" 17 | 18 | __all__ = [ 19 | 'dnssec', 20 | 'e164', 21 | 'edns', 22 | 'entropy', 23 | 'exception', 24 | 'flags', 25 | 'inet', 26 | 'ipv4', 27 | 'ipv6', 28 | 'message', 29 | 'name', 30 | 'namedict', 31 | 'node', 32 | 'opcode', 33 | 'query', 34 | 'rcode', 35 | 'rdata', 36 | 'rdataclass', 37 | 'rdataset', 38 | 'rdatatype', 39 | 'renderer', 40 | 'resolver', 41 | 'reversename', 42 | 'rrset', 43 | 'set', 44 | 'tokenizer', 45 | 'tsig', 46 | 'tsigkeyring', 47 | 'ttl', 48 | 'rdtypes', 49 | 'update', 50 | 'version', 51 | 'zone', 52 | ] 53 | -------------------------------------------------------------------------------- /third_party/dns/dnssec.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """Common DNSSEC-related functions and constants.""" 17 | 18 | RSAMD5 = 1 19 | DH = 2 20 | DSA = 3 21 | ECC = 4 22 | RSASHA1 = 5 23 | DSANSEC3SHA1 = 6 24 | RSASHA1NSEC3SHA1 = 7 25 | RSASHA256 = 8 26 | RSASHA512 = 10 27 | INDIRECT = 252 28 | PRIVATEDNS = 253 29 | PRIVATEOID = 254 30 | 31 | _algorithm_by_text = { 32 | 'RSAMD5' : RSAMD5, 33 | 'DH' : DH, 34 | 'DSA' : DSA, 35 | 'ECC' : ECC, 36 | 'RSASHA1' : RSASHA1, 37 | 'DSANSEC3SHA1' : DSANSEC3SHA1, 38 | 'RSASHA1NSEC3SHA1' : RSASHA1NSEC3SHA1, 39 | 'RSASHA256' : RSASHA256, 40 | 'RSASHA512' : RSASHA512, 41 | 'INDIRECT' : INDIRECT, 42 | 'PRIVATEDNS' : PRIVATEDNS, 43 | 'PRIVATEOID' : PRIVATEOID, 44 | } 45 | 46 | # We construct the inverse mapping programmatically to ensure that we 47 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 48 | # would cause the mapping not to be true inverse. 49 | 50 | _algorithm_by_value = dict([(y, x) for x, y in _algorithm_by_text.iteritems()]) 51 | 52 | class UnknownAlgorithm(Exception): 53 | """Raised if an algorithm is unknown.""" 54 | pass 55 | 56 | def algorithm_from_text(text): 57 | """Convert text into a DNSSEC algorithm value 58 | @rtype: int""" 59 | 60 | value = _algorithm_by_text.get(text.upper()) 61 | if value is None: 62 | value = int(text) 63 | return value 64 | 65 | def algorithm_to_text(value): 66 | """Convert a DNSSEC algorithm value to text 67 | @rtype: string""" 68 | 69 | text = _algorithm_by_value.get(value) 70 | if text is None: 71 | text = str(value) 72 | return text 73 | -------------------------------------------------------------------------------- /third_party/dns/e164.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006, 2007, 2009 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS E.164 helpers 17 | 18 | @var public_enum_domain: The DNS public ENUM domain, e164.arpa. 19 | @type public_enum_domain: dns.name.Name object 20 | """ 21 | 22 | import dns.exception 23 | import dns.name 24 | import dns.resolver 25 | 26 | public_enum_domain = dns.name.from_text('e164.arpa.') 27 | 28 | def from_e164(text, origin=public_enum_domain): 29 | """Convert an E.164 number in textual form into a Name object whose 30 | value is the ENUM domain name for that number. 31 | @param text: an E.164 number in textual form. 32 | @type text: str 33 | @param origin: The domain in which the number should be constructed. 34 | The default is e164.arpa. 35 | @type: dns.name.Name object or None 36 | @rtype: dns.name.Name object 37 | """ 38 | parts = [d for d in text if d.isdigit()] 39 | parts.reverse() 40 | return dns.name.from_text('.'.join(parts), origin=origin) 41 | 42 | def to_e164(name, origin=public_enum_domain, want_plus_prefix=True): 43 | """Convert an ENUM domain name into an E.164 number. 44 | @param name: the ENUM domain name. 45 | @type name: dns.name.Name object. 46 | @param origin: A domain containing the ENUM domain name. The 47 | name is relativized to this domain before being converted to text. 48 | @type: dns.name.Name object or None 49 | @param want_plus_prefix: if True, add a '+' to the beginning of the 50 | returned number. 51 | @rtype: str 52 | """ 53 | if not origin is None: 54 | name = name.relativize(origin) 55 | dlabels = [d for d in name.labels if (d.isdigit() and len(d) == 1)] 56 | if len(dlabels) != len(name.labels): 57 | raise dns.exception.SyntaxError('non-digit labels in ENUM domain name') 58 | dlabels.reverse() 59 | text = ''.join(dlabels) 60 | if want_plus_prefix: 61 | text = '+' + text 62 | return text 63 | 64 | def query(number, domains, resolver=None): 65 | """Look for NAPTR RRs for the specified number in the specified domains. 66 | 67 | e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.']) 68 | """ 69 | if resolver is None: 70 | resolver = dns.resolver.get_default_resolver() 71 | for domain in domains: 72 | if isinstance(domain, (str, unicode)): 73 | domain = dns.name.from_text(domain) 74 | qname = dns.e164.from_e164(number, domain) 75 | try: 76 | return resolver.query(qname, 'NAPTR') 77 | except dns.resolver.NXDOMAIN: 78 | pass 79 | raise dns.resolver.NXDOMAIN 80 | -------------------------------------------------------------------------------- /third_party/dns/edns.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """EDNS Options""" 17 | 18 | NSID = 3 19 | 20 | class Option(object): 21 | """Base class for all EDNS option types. 22 | """ 23 | 24 | def __init__(self, otype): 25 | """Initialize an option. 26 | @param rdtype: The rdata type 27 | @type rdtype: int 28 | """ 29 | self.otype = otype 30 | 31 | def to_wire(self, file): 32 | """Convert an option to wire format. 33 | """ 34 | raise NotImplementedError 35 | 36 | def from_wire(cls, otype, wire, current, olen): 37 | """Build an EDNS option object from wire format 38 | 39 | @param otype: The option type 40 | @type otype: int 41 | @param wire: The wire-format message 42 | @type wire: string 43 | @param current: The offet in wire of the beginning of the rdata. 44 | @type current: int 45 | @param olen: The length of the wire-format option data 46 | @type olen: int 47 | @rtype: dns.ends.Option instance""" 48 | raise NotImplementedError 49 | 50 | from_wire = classmethod(from_wire) 51 | 52 | def _cmp(self, other): 53 | """Compare an ENDS option with another option of the same type. 54 | Return < 0 if self < other, 0 if self == other, and > 0 if self > other. 55 | """ 56 | raise NotImplementedError 57 | 58 | def __eq__(self, other): 59 | if not isinstance(other, Option): 60 | return False 61 | if self.otype != other.otype: 62 | return False 63 | return self._cmp(other) == 0 64 | 65 | def __ne__(self, other): 66 | if not isinstance(other, Option): 67 | return False 68 | if self.otype != other.otype: 69 | return False 70 | return self._cmp(other) != 0 71 | 72 | def __lt__(self, other): 73 | if not isinstance(other, Option) or \ 74 | self.otype != other.otype: 75 | return NotImplemented 76 | return self._cmp(other) < 0 77 | 78 | def __le__(self, other): 79 | if not isinstance(other, Option) or \ 80 | self.otype != other.otype: 81 | return NotImplemented 82 | return self._cmp(other) <= 0 83 | 84 | def __ge__(self, other): 85 | if not isinstance(other, Option) or \ 86 | self.otype != other.otype: 87 | return NotImplemented 88 | return self._cmp(other) >= 0 89 | 90 | def __gt__(self, other): 91 | if not isinstance(other, Option) or \ 92 | self.otype != other.otype: 93 | return NotImplemented 94 | return self._cmp(other) > 0 95 | 96 | 97 | class GenericOption(Option): 98 | """Generate Rdata Class 99 | 100 | This class is used for EDNS option types for which we have no better 101 | implementation. 102 | """ 103 | 104 | def __init__(self, otype, data): 105 | super(GenericOption, self).__init__(otype) 106 | self.data = data 107 | 108 | def to_wire(self, file): 109 | file.write(self.data) 110 | 111 | def from_wire(cls, otype, wire, current, olen): 112 | return cls(otype, wire[current : current + olen]) 113 | 114 | from_wire = classmethod(from_wire) 115 | 116 | def _cmp(self, other): 117 | return cmp(self.data, other.data) 118 | 119 | _type_to_class = { 120 | } 121 | 122 | def get_option_class(otype): 123 | cls = _type_to_class.get(otype) 124 | if cls is None: 125 | cls = GenericOption 126 | return cls 127 | 128 | def option_from_wire(otype, wire, current, olen): 129 | """Build an EDNS option object from wire format 130 | 131 | @param otype: The option type 132 | @type otype: int 133 | @param wire: The wire-format message 134 | @type wire: string 135 | @param current: The offet in wire of the beginning of the rdata. 136 | @type current: int 137 | @param olen: The length of the wire-format option data 138 | @type olen: int 139 | @rtype: dns.ends.Option instance""" 140 | 141 | cls = get_option_class(otype) 142 | return cls.from_wire(otype, wire, current, olen) 143 | -------------------------------------------------------------------------------- /third_party/dns/entropy.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import os 17 | import time 18 | try: 19 | import threading as _threading 20 | except ImportError: 21 | import dummy_threading as _threading 22 | 23 | class EntropyPool(object): 24 | def __init__(self, seed=None): 25 | self.pool_index = 0 26 | self.digest = None 27 | self.next_byte = 0 28 | self.lock = _threading.Lock() 29 | try: 30 | import hashlib 31 | self.hash = hashlib.sha1() 32 | self.hash_len = 20 33 | except: 34 | try: 35 | import sha 36 | self.hash = sha.new() 37 | self.hash_len = 20 38 | except: 39 | import md5 40 | self.hash = md5.new() 41 | self.hash_len = 16 42 | self.pool = '\0' * self.hash_len 43 | if not seed is None: 44 | self.stir(seed) 45 | self.seeded = True 46 | else: 47 | self.seeded = False 48 | 49 | def stir(self, entropy, already_locked=False): 50 | if not already_locked: 51 | self.lock.acquire() 52 | try: 53 | bytes = [ord(c) for c in self.pool] 54 | for c in entropy: 55 | if self.pool_index == self.hash_len: 56 | self.pool_index = 0 57 | b = ord(c) & 0xff 58 | bytes[self.pool_index] ^= b 59 | self.pool_index += 1 60 | self.pool = ''.join([chr(c) for c in bytes]) 61 | finally: 62 | if not already_locked: 63 | self.lock.release() 64 | 65 | def _maybe_seed(self): 66 | if not self.seeded: 67 | try: 68 | seed = os.urandom(16) 69 | except: 70 | try: 71 | r = file('/dev/urandom', 'r', 0) 72 | try: 73 | seed = r.read(16) 74 | finally: 75 | r.close() 76 | except: 77 | seed = str(time.time()) 78 | self.seeded = True 79 | self.stir(seed, True) 80 | 81 | def random_8(self): 82 | self.lock.acquire() 83 | self._maybe_seed() 84 | try: 85 | if self.digest is None or self.next_byte == self.hash_len: 86 | self.hash.update(self.pool) 87 | self.digest = self.hash.digest() 88 | self.stir(self.digest, True) 89 | self.next_byte = 0 90 | value = ord(self.digest[self.next_byte]) 91 | self.next_byte += 1 92 | finally: 93 | self.lock.release() 94 | return value 95 | 96 | def random_16(self): 97 | return self.random_8() * 256 + self.random_8() 98 | 99 | def random_32(self): 100 | return self.random_16() * 65536 + self.random_16() 101 | 102 | def random_between(self, first, last): 103 | size = last - first + 1 104 | if size > 4294967296L: 105 | raise ValueError('too big') 106 | if size > 65536: 107 | rand = self.random_32 108 | max = 4294967295L 109 | elif size > 256: 110 | rand = self.random_16 111 | max = 65535 112 | else: 113 | rand = self.random_8 114 | max = 255 115 | return (first + size * rand() // (max + 1)) 116 | 117 | pool = EntropyPool() 118 | 119 | def random_16(): 120 | return pool.random_16() 121 | 122 | def between(first, last): 123 | return pool.random_between(first, last) 124 | -------------------------------------------------------------------------------- /third_party/dns/exception.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """Common DNS Exceptions.""" 17 | 18 | class DNSException(Exception): 19 | """Abstract base class shared by all dnspython exceptions.""" 20 | pass 21 | 22 | class FormError(DNSException): 23 | """DNS message is malformed.""" 24 | pass 25 | 26 | class SyntaxError(DNSException): 27 | """Text input is malformed.""" 28 | pass 29 | 30 | class UnexpectedEnd(SyntaxError): 31 | """Raised if text input ends unexpectedly.""" 32 | pass 33 | 34 | class TooBig(DNSException): 35 | """The message is too big.""" 36 | pass 37 | 38 | class Timeout(DNSException): 39 | """The operation timed out.""" 40 | pass 41 | -------------------------------------------------------------------------------- /third_party/dns/flags.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS Message Flags.""" 17 | 18 | # Standard DNS flags 19 | 20 | QR = 0x8000 21 | AA = 0x0400 22 | TC = 0x0200 23 | RD = 0x0100 24 | RA = 0x0080 25 | AD = 0x0020 26 | CD = 0x0010 27 | 28 | # EDNS flags 29 | 30 | DO = 0x8000 31 | 32 | _by_text = { 33 | 'QR' : QR, 34 | 'AA' : AA, 35 | 'TC' : TC, 36 | 'RD' : RD, 37 | 'RA' : RA, 38 | 'AD' : AD, 39 | 'CD' : CD 40 | } 41 | 42 | _edns_by_text = { 43 | 'DO' : DO 44 | } 45 | 46 | 47 | # We construct the inverse mappings programmatically to ensure that we 48 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 49 | # would cause the mappings not to be true inverses. 50 | 51 | _by_value = dict([(y, x) for x, y in _by_text.iteritems()]) 52 | 53 | _edns_by_value = dict([(y, x) for x, y in _edns_by_text.iteritems()]) 54 | 55 | def _order_flags(table): 56 | order = list(table.iteritems()) 57 | order.sort() 58 | order.reverse() 59 | return order 60 | 61 | _flags_order = _order_flags(_by_value) 62 | 63 | _edns_flags_order = _order_flags(_edns_by_value) 64 | 65 | def _from_text(text, table): 66 | flags = 0 67 | tokens = text.split() 68 | for t in tokens: 69 | flags = flags | table[t.upper()] 70 | return flags 71 | 72 | def _to_text(flags, table, order): 73 | text_flags = [] 74 | for k, v in order: 75 | if flags & k != 0: 76 | text_flags.append(v) 77 | return ' '.join(text_flags) 78 | 79 | def from_text(text): 80 | """Convert a space-separated list of flag text values into a flags 81 | value. 82 | @rtype: int""" 83 | 84 | return _from_text(text, _by_text) 85 | 86 | def to_text(flags): 87 | """Convert a flags value into a space-separated list of flag text 88 | values. 89 | @rtype: string""" 90 | 91 | return _to_text(flags, _by_value, _flags_order) 92 | 93 | 94 | def edns_from_text(text): 95 | """Convert a space-separated list of EDNS flag text values into a EDNS 96 | flags value. 97 | @rtype: int""" 98 | 99 | return _from_text(text, _edns_by_text) 100 | 101 | def edns_to_text(flags): 102 | """Convert an EDNS flags value into a space-separated list of EDNS flag 103 | text values. 104 | @rtype: string""" 105 | 106 | return _to_text(flags, _edns_by_value, _edns_flags_order) 107 | -------------------------------------------------------------------------------- /third_party/dns/inet.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """Generic Internet address helper functions.""" 17 | 18 | import socket 19 | 20 | import dns.ipv4 21 | import dns.ipv6 22 | 23 | 24 | # We assume that AF_INET is always defined. 25 | 26 | AF_INET = socket.AF_INET 27 | 28 | # AF_INET6 might not be defined in the socket module, but we need it. 29 | # We'll try to use the socket module's value, and if it doesn't work, 30 | # we'll use our own value. 31 | 32 | try: 33 | AF_INET6 = socket.AF_INET6 34 | except AttributeError: 35 | AF_INET6 = 9999 36 | 37 | def inet_pton(family, text): 38 | """Convert the textual form of a network address into its binary form. 39 | 40 | @param family: the address family 41 | @type family: int 42 | @param text: the textual address 43 | @type text: string 44 | @raises NotImplementedError: the address family specified is not 45 | implemented. 46 | @rtype: string 47 | """ 48 | 49 | if family == AF_INET: 50 | return dns.ipv4.inet_aton(text) 51 | elif family == AF_INET6: 52 | return dns.ipv6.inet_aton(text) 53 | else: 54 | raise NotImplementedError 55 | 56 | def inet_ntop(family, address): 57 | """Convert the binary form of a network address into its textual form. 58 | 59 | @param family: the address family 60 | @type family: int 61 | @param address: the binary address 62 | @type address: string 63 | @raises NotImplementedError: the address family specified is not 64 | implemented. 65 | @rtype: string 66 | """ 67 | if family == AF_INET: 68 | return dns.ipv4.inet_ntoa(address) 69 | elif family == AF_INET6: 70 | return dns.ipv6.inet_ntoa(address) 71 | else: 72 | raise NotImplementedError 73 | 74 | def af_for_address(text): 75 | """Determine the address family of a textual-form network address. 76 | 77 | @param text: the textual address 78 | @type text: string 79 | @raises ValueError: the address family cannot be determined from the input. 80 | @rtype: int 81 | """ 82 | try: 83 | junk = dns.ipv4.inet_aton(text) 84 | return AF_INET 85 | except: 86 | try: 87 | junk = dns.ipv6.inet_aton(text) 88 | return AF_INET6 89 | except: 90 | raise ValueError 91 | 92 | def is_multicast(text): 93 | """Is the textual-form network address a multicast address? 94 | 95 | @param text: the textual address 96 | @raises ValueError: the address family cannot be determined from the input. 97 | @rtype: bool 98 | """ 99 | try: 100 | first = ord(dns.ipv4.inet_aton(text)[0]) 101 | return (first >= 224 and first <= 239) 102 | except: 103 | try: 104 | first = ord(dns.ipv6.inet_aton(text)[0]) 105 | return (first == 255) 106 | except: 107 | raise ValueError 108 | 109 | -------------------------------------------------------------------------------- /third_party/dns/ipv4.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """IPv4 helper functions.""" 17 | 18 | import socket 19 | import sys 20 | 21 | if sys.hexversion < 0x02030000 or sys.platform == 'win32': 22 | # 23 | # Some versions of Python 2.2 have an inet_aton which rejects 24 | # the valid IP address '255.255.255.255'. It appears this 25 | # problem is still present on the Win32 platform even in 2.3. 26 | # We'll work around the problem. 27 | # 28 | def inet_aton(text): 29 | if text == '255.255.255.255': 30 | return '\xff' * 4 31 | else: 32 | return socket.inet_aton(text) 33 | else: 34 | inet_aton = socket.inet_aton 35 | 36 | inet_ntoa = socket.inet_ntoa 37 | -------------------------------------------------------------------------------- /third_party/dns/namedict.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS name dictionary""" 17 | 18 | import dns.name 19 | 20 | class NameDict(dict): 21 | 22 | """A dictionary whose keys are dns.name.Name objects. 23 | @ivar max_depth: the maximum depth of the keys that have ever been 24 | added to the dictionary. 25 | @type max_depth: int 26 | """ 27 | 28 | def __init__(self, *args, **kwargs): 29 | super(NameDict, self).__init__(*args, **kwargs) 30 | self.max_depth = 0 31 | 32 | def __setitem__(self, key, value): 33 | if not isinstance(key, dns.name.Name): 34 | raise ValueError('NameDict key must be a name') 35 | depth = len(key) 36 | if depth > self.max_depth: 37 | self.max_depth = depth 38 | super(NameDict, self).__setitem__(key, value) 39 | 40 | def get_deepest_match(self, name): 41 | """Find the deepest match to I{name} in the dictionary. 42 | 43 | The deepest match is the longest name in the dictionary which is 44 | a superdomain of I{name}. 45 | 46 | @param name: the name 47 | @type name: dns.name.Name object 48 | @rtype: (key, value) tuple 49 | """ 50 | 51 | depth = len(name) 52 | if depth > self.max_depth: 53 | depth = self.max_depth 54 | for i in xrange(-depth, 0): 55 | n = dns.name.Name(name[i:]) 56 | if self.has_key(n): 57 | return (n, self[n]) 58 | v = self[dns.name.empty] 59 | return (dns.name.empty, v) 60 | -------------------------------------------------------------------------------- /third_party/dns/opcode.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS Opcodes.""" 17 | 18 | import dns.exception 19 | 20 | QUERY = 0 21 | IQUERY = 1 22 | STATUS = 2 23 | NOTIFY = 4 24 | UPDATE = 5 25 | 26 | _by_text = { 27 | 'QUERY' : QUERY, 28 | 'IQUERY' : IQUERY, 29 | 'STATUS' : STATUS, 30 | 'NOTIFY' : NOTIFY, 31 | 'UPDATE' : UPDATE 32 | } 33 | 34 | # We construct the inverse mapping programmatically to ensure that we 35 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 36 | # would cause the mapping not to be true inverse. 37 | 38 | _by_value = dict([(y, x) for x, y in _by_text.iteritems()]) 39 | 40 | 41 | class UnknownOpcode(dns.exception.DNSException): 42 | """Raised if an opcode is unknown.""" 43 | pass 44 | 45 | def from_text(text): 46 | """Convert text into an opcode. 47 | 48 | @param text: the textual opcode 49 | @type text: string 50 | @raises UnknownOpcode: the opcode is unknown 51 | @rtype: int 52 | """ 53 | 54 | if text.isdigit(): 55 | value = int(text) 56 | if value >= 0 and value <= 15: 57 | return value 58 | value = _by_text.get(text.upper()) 59 | if value is None: 60 | raise UnknownOpcode 61 | return value 62 | 63 | def from_flags(flags): 64 | """Extract an opcode from DNS message flags. 65 | 66 | @param flags: int 67 | @rtype: int 68 | """ 69 | 70 | return (flags & 0x7800) >> 11 71 | 72 | def to_flags(value): 73 | """Convert an opcode to a value suitable for ORing into DNS message 74 | flags. 75 | @rtype: int 76 | """ 77 | 78 | return (value << 11) & 0x7800 79 | 80 | def to_text(value): 81 | """Convert an opcode to text. 82 | 83 | @param value: the opcdoe 84 | @type value: int 85 | @raises UnknownOpcode: the opcode is unknown 86 | @rtype: string 87 | """ 88 | 89 | text = _by_value.get(value) 90 | if text is None: 91 | text = str(value) 92 | return text 93 | 94 | def is_update(flags): 95 | """True if the opcode in flags is UPDATE. 96 | 97 | @param flags: DNS flags 98 | @type flags: int 99 | @rtype: bool 100 | """ 101 | 102 | if (from_flags(flags) == UPDATE): 103 | return True 104 | return False 105 | -------------------------------------------------------------------------------- /third_party/dns/rcode.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS Result Codes.""" 17 | 18 | import dns.exception 19 | 20 | NOERROR = 0 21 | FORMERR = 1 22 | SERVFAIL = 2 23 | NXDOMAIN = 3 24 | NOTIMP = 4 25 | REFUSED = 5 26 | YXDOMAIN = 6 27 | YXRRSET = 7 28 | NXRRSET = 8 29 | NOTAUTH = 9 30 | NOTZONE = 10 31 | BADVERS = 16 32 | 33 | _by_text = { 34 | 'NOERROR' : NOERROR, 35 | 'FORMERR' : FORMERR, 36 | 'SERVFAIL' : SERVFAIL, 37 | 'NXDOMAIN' : NXDOMAIN, 38 | 'NOTIMP' : NOTIMP, 39 | 'REFUSED' : REFUSED, 40 | 'YXDOMAIN' : YXDOMAIN, 41 | 'YXRRSET' : YXRRSET, 42 | 'NXRRSET' : NXRRSET, 43 | 'NOTAUTH' : NOTAUTH, 44 | 'NOTZONE' : NOTZONE, 45 | 'BADVERS' : BADVERS 46 | } 47 | 48 | # We construct the inverse mapping programmatically to ensure that we 49 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 50 | # would cause the mapping not to be a true inverse. 51 | 52 | _by_value = dict([(y, x) for x, y in _by_text.iteritems()]) 53 | 54 | 55 | class UnknownRcode(dns.exception.DNSException): 56 | """Raised if an rcode is unknown.""" 57 | pass 58 | 59 | def from_text(text): 60 | """Convert text into an rcode. 61 | 62 | @param text: the texual rcode 63 | @type text: string 64 | @raises UnknownRcode: the rcode is unknown 65 | @rtype: int 66 | """ 67 | 68 | if text.isdigit(): 69 | v = int(text) 70 | if v >= 0 and v <= 4095: 71 | return v 72 | v = _by_text.get(text.upper()) 73 | if v is None: 74 | raise UnknownRcode 75 | return v 76 | 77 | def from_flags(flags, ednsflags): 78 | """Return the rcode value encoded by flags and ednsflags. 79 | 80 | @param flags: the DNS flags 81 | @type flags: int 82 | @param ednsflags: the EDNS flags 83 | @type ednsflags: int 84 | @raises ValueError: rcode is < 0 or > 4095 85 | @rtype: int 86 | """ 87 | 88 | value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0) 89 | if value < 0 or value > 4095: 90 | raise ValueError('rcode must be >= 0 and <= 4095') 91 | return value 92 | 93 | def to_flags(value): 94 | """Return a (flags, ednsflags) tuple which encodes the rcode. 95 | 96 | @param value: the rcode 97 | @type value: int 98 | @raises ValueError: rcode is < 0 or > 4095 99 | @rtype: (int, int) tuple 100 | """ 101 | 102 | if value < 0 or value > 4095: 103 | raise ValueError('rcode must be >= 0 and <= 4095') 104 | v = value & 0xf 105 | ev = long(value & 0xff0) << 20 106 | return (v, ev) 107 | 108 | def to_text(value): 109 | """Convert rcode into text. 110 | 111 | @param value: the rcode 112 | @type value: int 113 | @rtype: string 114 | """ 115 | 116 | text = _by_value.get(value) 117 | if text is None: 118 | text = str(value) 119 | return text 120 | -------------------------------------------------------------------------------- /third_party/dns/rdataclass.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS Rdata Classes. 17 | 18 | @var _by_text: The rdata class textual name to value mapping 19 | @type _by_text: dict 20 | @var _by_value: The rdata class value to textual name mapping 21 | @type _by_value: dict 22 | @var _metaclasses: If an rdataclass is a metaclass, there will be a mapping 23 | whose key is the rdatatype value and whose value is True in this dictionary. 24 | @type _metaclasses: dict""" 25 | 26 | import re 27 | 28 | import dns.exception 29 | 30 | RESERVED0 = 0 31 | IN = 1 32 | CH = 3 33 | HS = 4 34 | NONE = 254 35 | ANY = 255 36 | 37 | _by_text = { 38 | 'RESERVED0' : RESERVED0, 39 | 'IN' : IN, 40 | 'CH' : CH, 41 | 'HS' : HS, 42 | 'NONE' : NONE, 43 | 'ANY' : ANY 44 | } 45 | 46 | # We construct the inverse mapping programmatically to ensure that we 47 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 48 | # would cause the mapping not to be true inverse. 49 | 50 | _by_value = dict([(y, x) for x, y in _by_text.iteritems()]) 51 | 52 | # Now that we've built the inverse map, we can add class aliases to 53 | # the _by_text mapping. 54 | 55 | _by_text.update({ 56 | 'INTERNET' : IN, 57 | 'CHAOS' : CH, 58 | 'HESIOD' : HS 59 | }) 60 | 61 | _metaclasses = { 62 | NONE : True, 63 | ANY : True 64 | } 65 | 66 | _unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I); 67 | 68 | class UnknownRdataclass(dns.exception.DNSException): 69 | """Raised when a class is unknown.""" 70 | pass 71 | 72 | def from_text(text): 73 | """Convert text into a DNS rdata class value. 74 | @param text: the text 75 | @type text: string 76 | @rtype: int 77 | @raises dns.rdataclass.UnknownRdataClass: the class is unknown 78 | @raises ValueError: the rdata class value is not >= 0 and <= 65535 79 | """ 80 | 81 | value = _by_text.get(text.upper()) 82 | if value is None: 83 | match = _unknown_class_pattern.match(text) 84 | if match == None: 85 | raise UnknownRdataclass 86 | value = int(match.group(1)) 87 | if value < 0 or value > 65535: 88 | raise ValueError("class must be between >= 0 and <= 65535") 89 | return value 90 | 91 | def to_text(value): 92 | """Convert a DNS rdata class to text. 93 | @param value: the rdata class value 94 | @type value: int 95 | @rtype: string 96 | @raises ValueError: the rdata class value is not >= 0 and <= 65535 97 | """ 98 | 99 | if value < 0 or value > 65535: 100 | raise ValueError("class must be between >= 0 and <= 65535") 101 | text = _by_value.get(value) 102 | if text is None: 103 | text = 'CLASS' + `value` 104 | return text 105 | 106 | def is_metaclass(rdclass): 107 | """True if the class is a metaclass. 108 | @param rdclass: the rdata class 109 | @type rdclass: int 110 | @rtype: bool""" 111 | 112 | if _metaclasses.has_key(rdclass): 113 | return True 114 | return False 115 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/AFSDB.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.mxbase 17 | 18 | class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX): 19 | """AFSDB record 20 | 21 | @ivar subtype: the subtype value 22 | @type subtype: int 23 | @ivar hostname: the hostname name 24 | @type hostname: dns.name.Name object""" 25 | 26 | # Use the property mechanism to make "subtype" an alias for the 27 | # "preference" attribute, and "hostname" an alias for the "exchange" 28 | # attribute. 29 | # 30 | # This lets us inherit the UncompressedMX implementation but lets 31 | # the caller use appropriate attribute names for the rdata type. 32 | # 33 | # We probably lose some performance vs. a cut-and-paste 34 | # implementation, but this way we don't copy code, and that's 35 | # good. 36 | 37 | def get_subtype(self): 38 | return self.preference 39 | 40 | def set_subtype(self, subtype): 41 | self.preference = subtype 42 | 43 | subtype = property(get_subtype, set_subtype) 44 | 45 | def get_hostname(self): 46 | return self.exchange 47 | 48 | def set_hostname(self, hostname): 49 | self.exchange = hostname 50 | 51 | hostname = property(get_hostname, set_hostname) 52 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/CERT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import cStringIO 17 | import struct 18 | 19 | import dns.exception 20 | import dns.dnssec 21 | import dns.rdata 22 | import dns.tokenizer 23 | 24 | _ctype_by_value = { 25 | 1 : 'PKIX', 26 | 2 : 'SPKI', 27 | 3 : 'PGP', 28 | 253 : 'URI', 29 | 254 : 'OID', 30 | } 31 | 32 | _ctype_by_name = { 33 | 'PKIX' : 1, 34 | 'SPKI' : 2, 35 | 'PGP' : 3, 36 | 'URI' : 253, 37 | 'OID' : 254, 38 | } 39 | 40 | def _ctype_from_text(what): 41 | v = _ctype_by_name.get(what) 42 | if not v is None: 43 | return v 44 | return int(what) 45 | 46 | def _ctype_to_text(what): 47 | v = _ctype_by_value.get(what) 48 | if not v is None: 49 | return v 50 | return str(what) 51 | 52 | class CERT(dns.rdata.Rdata): 53 | """CERT record 54 | 55 | @ivar certificate_type: certificate type 56 | @type certificate_type: int 57 | @ivar key_tag: key tag 58 | @type key_tag: int 59 | @ivar algorithm: algorithm 60 | @type algorithm: int 61 | @ivar certificate: the certificate or CRL 62 | @type certificate: string 63 | @see: RFC 2538""" 64 | 65 | __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate'] 66 | 67 | def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm, 68 | certificate): 69 | super(CERT, self).__init__(rdclass, rdtype) 70 | self.certificate_type = certificate_type 71 | self.key_tag = key_tag 72 | self.algorithm = algorithm 73 | self.certificate = certificate 74 | 75 | def to_text(self, origin=None, relativize=True, **kw): 76 | certificate_type = _ctype_to_text(self.certificate_type) 77 | return "%s %d %s %s" % (certificate_type, self.key_tag, 78 | dns.dnssec.algorithm_to_text(self.algorithm), 79 | dns.rdata._base64ify(self.certificate)) 80 | 81 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 82 | certificate_type = _ctype_from_text(tok.get_string()) 83 | key_tag = tok.get_uint16() 84 | algorithm = dns.dnssec.algorithm_from_text(tok.get_string()) 85 | if algorithm < 0 or algorithm > 255: 86 | raise dns.exception.SyntaxError("bad algorithm type") 87 | chunks = [] 88 | while 1: 89 | t = tok.get().unescape() 90 | if t.is_eol_or_eof(): 91 | break 92 | if not t.is_identifier(): 93 | raise dns.exception.SyntaxError 94 | chunks.append(t.value) 95 | b64 = ''.join(chunks) 96 | certificate = b64.decode('base64_codec') 97 | return cls(rdclass, rdtype, certificate_type, key_tag, 98 | algorithm, certificate) 99 | 100 | from_text = classmethod(from_text) 101 | 102 | def to_wire(self, file, compress = None, origin = None): 103 | prefix = struct.pack("!HHB", self.certificate_type, self.key_tag, 104 | self.algorithm) 105 | file.write(prefix) 106 | file.write(self.certificate) 107 | 108 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 109 | prefix = wire[current : current + 5] 110 | current += 5 111 | rdlen -= 5 112 | if rdlen < 0: 113 | raise dns.exception.FormError 114 | (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix) 115 | certificate = wire[current : current + rdlen] 116 | return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, 117 | certificate) 118 | 119 | from_wire = classmethod(from_wire) 120 | 121 | def _cmp(self, other): 122 | f = cStringIO.StringIO() 123 | self.to_wire(f) 124 | wire1 = f.getvalue() 125 | f.seek(0) 126 | f.truncate() 127 | other.to_wire(f) 128 | wire2 = f.getvalue() 129 | f.close() 130 | 131 | return cmp(wire1, wire2) 132 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/CNAME.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.nsbase 17 | 18 | class CNAME(dns.rdtypes.nsbase.NSBase): 19 | """CNAME record 20 | 21 | Note: although CNAME is officially a singleton type, dnspython allows 22 | non-singleton CNAME rdatasets because such sets have been commonly 23 | used by BIND and other nameservers for load balancing.""" 24 | pass 25 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/DLV.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.dsbase 17 | 18 | class DLV(dns.rdtypes.dsbase.DSBase): 19 | """DLV record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/DNAME.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.nsbase 17 | 18 | class DNAME(dns.rdtypes.nsbase.UncompressedNS): 19 | """DNAME record""" 20 | def to_digestable(self, origin = None): 21 | return self.target.to_digestable(origin) 22 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/DNSKEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.keybase 17 | 18 | # flag constants 19 | SEP = 0x0001 20 | REVOKE = 0x0080 21 | ZONE = 0x0100 22 | 23 | class DNSKEY(dns.rdtypes.keybase.KEYBase): 24 | """DNSKEY record""" 25 | pass 26 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/DS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.dsbase 17 | 18 | class DS(dns.rdtypes.dsbase.DSBase): 19 | """DS record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/HINFO.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.tokenizer 19 | 20 | class HINFO(dns.rdata.Rdata): 21 | """HINFO record 22 | 23 | @ivar cpu: the CPU type 24 | @type cpu: string 25 | @ivar os: the OS type 26 | @type os: string 27 | @see: RFC 1035""" 28 | 29 | __slots__ = ['cpu', 'os'] 30 | 31 | def __init__(self, rdclass, rdtype, cpu, os): 32 | super(HINFO, self).__init__(rdclass, rdtype) 33 | self.cpu = cpu 34 | self.os = os 35 | 36 | def to_text(self, origin=None, relativize=True, **kw): 37 | return '"%s" "%s"' % (dns.rdata._escapify(self.cpu), 38 | dns.rdata._escapify(self.os)) 39 | 40 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 41 | cpu = tok.get_string() 42 | os = tok.get_string() 43 | tok.get_eol() 44 | return cls(rdclass, rdtype, cpu, os) 45 | 46 | from_text = classmethod(from_text) 47 | 48 | def to_wire(self, file, compress = None, origin = None): 49 | l = len(self.cpu) 50 | assert l < 256 51 | byte = chr(l) 52 | file.write(byte) 53 | file.write(self.cpu) 54 | l = len(self.os) 55 | assert l < 256 56 | byte = chr(l) 57 | file.write(byte) 58 | file.write(self.os) 59 | 60 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 61 | l = ord(wire[current]) 62 | current += 1 63 | rdlen -= 1 64 | if l > rdlen: 65 | raise dns.exception.FormError 66 | cpu = wire[current : current + l] 67 | current += l 68 | rdlen -= l 69 | l = ord(wire[current]) 70 | current += 1 71 | rdlen -= 1 72 | if l != rdlen: 73 | raise dns.exception.FormError 74 | os = wire[current : current + l] 75 | return cls(rdclass, rdtype, cpu, os) 76 | 77 | from_wire = classmethod(from_wire) 78 | 79 | def _cmp(self, other): 80 | v = cmp(self.cpu, other.cpu) 81 | if v == 0: 82 | v = cmp(self.os, other.os) 83 | return v 84 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/ISDN.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.tokenizer 19 | 20 | class ISDN(dns.rdata.Rdata): 21 | """ISDN record 22 | 23 | @ivar address: the ISDN address 24 | @type address: string 25 | @ivar subaddress: the ISDN subaddress (or '' if not present) 26 | @type subaddress: string 27 | @see: RFC 1183""" 28 | 29 | __slots__ = ['address', 'subaddress'] 30 | 31 | def __init__(self, rdclass, rdtype, address, subaddress): 32 | super(ISDN, self).__init__(rdclass, rdtype) 33 | self.address = address 34 | self.subaddress = subaddress 35 | 36 | def to_text(self, origin=None, relativize=True, **kw): 37 | if self.subaddress: 38 | return '"%s" "%s"' % (dns.rdata._escapify(self.address), 39 | dns.rdata._escapify(self.subaddress)) 40 | else: 41 | return '"%s"' % dns.rdata._escapify(self.address) 42 | 43 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 44 | address = tok.get_string() 45 | t = tok.get() 46 | if not t.is_eol_or_eof(): 47 | tok.unget(t) 48 | subaddress = tok.get_string() 49 | else: 50 | tok.unget(t) 51 | subaddress = '' 52 | tok.get_eol() 53 | return cls(rdclass, rdtype, address, subaddress) 54 | 55 | from_text = classmethod(from_text) 56 | 57 | def to_wire(self, file, compress = None, origin = None): 58 | l = len(self.address) 59 | assert l < 256 60 | byte = chr(l) 61 | file.write(byte) 62 | file.write(self.address) 63 | l = len(self.subaddress) 64 | if l > 0: 65 | assert l < 256 66 | byte = chr(l) 67 | file.write(byte) 68 | file.write(self.subaddress) 69 | 70 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 71 | l = ord(wire[current]) 72 | current += 1 73 | rdlen -= 1 74 | if l > rdlen: 75 | raise dns.exception.FormError 76 | address = wire[current : current + l] 77 | current += l 78 | rdlen -= l 79 | if rdlen > 0: 80 | l = ord(wire[current]) 81 | current += 1 82 | rdlen -= 1 83 | if l != rdlen: 84 | raise dns.exception.FormError 85 | subaddress = wire[current : current + l] 86 | else: 87 | subaddress = '' 88 | return cls(rdclass, rdtype, address, subaddress) 89 | 90 | from_wire = classmethod(from_wire) 91 | 92 | def _cmp(self, other): 93 | v = cmp(self.address, other.address) 94 | if v == 0: 95 | v = cmp(self.subaddress, other.subaddress) 96 | return v 97 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/KEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.keybase 17 | 18 | class KEY(dns.rdtypes.keybase.KEYBase): 19 | """KEY record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/MX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.mxbase 17 | 18 | class MX(dns.rdtypes.mxbase.MXBase): 19 | """MX record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/NS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.nsbase 17 | 18 | class NS(dns.rdtypes.nsbase.NSBase): 19 | """NS record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/NSEC3PARAM.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import cStringIO 17 | import struct 18 | 19 | import dns.exception 20 | import dns.rdata 21 | 22 | class NSEC3PARAM(dns.rdata.Rdata): 23 | """NSEC3PARAM record 24 | 25 | @ivar algorithm: the hash algorithm number 26 | @type algorithm: int 27 | @ivar flags: the flags 28 | @type flags: int 29 | @ivar iterations: the number of iterations 30 | @type iterations: int 31 | @ivar salt: the salt 32 | @type salt: string""" 33 | 34 | __slots__ = ['algorithm', 'flags', 'iterations', 'salt'] 35 | 36 | def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt): 37 | super(NSEC3PARAM, self).__init__(rdclass, rdtype) 38 | self.algorithm = algorithm 39 | self.flags = flags 40 | self.iterations = iterations 41 | self.salt = salt 42 | 43 | def to_text(self, origin=None, relativize=True, **kw): 44 | if self.salt == '': 45 | salt = '-' 46 | else: 47 | salt = self.salt.encode('hex-codec') 48 | return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations, salt) 49 | 50 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 51 | algorithm = tok.get_uint8() 52 | flags = tok.get_uint8() 53 | iterations = tok.get_uint16() 54 | salt = tok.get_string() 55 | if salt == '-': 56 | salt = '' 57 | else: 58 | salt = salt.decode('hex-codec') 59 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt) 60 | 61 | from_text = classmethod(from_text) 62 | 63 | def to_wire(self, file, compress = None, origin = None): 64 | l = len(self.salt) 65 | file.write(struct.pack("!BBHB", self.algorithm, self.flags, 66 | self.iterations, l)) 67 | file.write(self.salt) 68 | 69 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 70 | (algorithm, flags, iterations, slen) = struct.unpack('!BBHB', 71 | wire[current : current + 5]) 72 | current += 5 73 | rdlen -= 5 74 | salt = wire[current : current + slen] 75 | current += slen 76 | rdlen -= slen 77 | if rdlen != 0: 78 | raise dns.exception.FormError 79 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt) 80 | 81 | from_wire = classmethod(from_wire) 82 | 83 | def _cmp(self, other): 84 | b1 = cStringIO.StringIO() 85 | self.to_wire(b1) 86 | b2 = cStringIO.StringIO() 87 | other.to_wire(b2) 88 | return cmp(b1.getvalue(), b2.getvalue()) 89 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/NXT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.rdatatype 19 | import dns.name 20 | 21 | class NXT(dns.rdata.Rdata): 22 | """NXT record 23 | 24 | @ivar next: the next name 25 | @type next: dns.name.Name object 26 | @ivar bitmap: the type bitmap 27 | @type bitmap: string 28 | @see: RFC 2535""" 29 | 30 | __slots__ = ['next', 'bitmap'] 31 | 32 | def __init__(self, rdclass, rdtype, next, bitmap): 33 | super(NXT, self).__init__(rdclass, rdtype) 34 | self.next = next 35 | self.bitmap = bitmap 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | next = self.next.choose_relativity(origin, relativize) 39 | bits = [] 40 | for i in xrange(0, len(self.bitmap)): 41 | byte = ord(self.bitmap[i]) 42 | for j in xrange(0, 8): 43 | if byte & (0x80 >> j): 44 | bits.append(dns.rdatatype.to_text(i * 8 + j)) 45 | text = ' '.join(bits) 46 | return '%s %s' % (next, text) 47 | 48 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 49 | next = tok.get_name() 50 | next = next.choose_relativity(origin, relativize) 51 | bitmap = ['\x00', '\x00', '\x00', '\x00', 52 | '\x00', '\x00', '\x00', '\x00', 53 | '\x00', '\x00', '\x00', '\x00', 54 | '\x00', '\x00', '\x00', '\x00' ] 55 | while 1: 56 | token = tok.get().unescape() 57 | if token.is_eol_or_eof(): 58 | break 59 | if token.value.isdigit(): 60 | nrdtype = int(token.value) 61 | else: 62 | nrdtype = dns.rdatatype.from_text(token.value) 63 | if nrdtype == 0: 64 | raise dns.exception.SyntaxError("NXT with bit 0") 65 | if nrdtype > 127: 66 | raise dns.exception.SyntaxError("NXT with bit > 127") 67 | i = nrdtype // 8 68 | bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (nrdtype % 8))) 69 | bitmap = dns.rdata._truncate_bitmap(bitmap) 70 | return cls(rdclass, rdtype, next, bitmap) 71 | 72 | from_text = classmethod(from_text) 73 | 74 | def to_wire(self, file, compress = None, origin = None): 75 | self.next.to_wire(file, None, origin) 76 | file.write(self.bitmap) 77 | 78 | def to_digestable(self, origin = None): 79 | return self.next.to_digestable(origin) + self.bitmap 80 | 81 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 82 | (next, cused) = dns.name.from_wire(wire[: current + rdlen], current) 83 | current += cused 84 | rdlen -= cused 85 | bitmap = wire[current : current + rdlen] 86 | if not origin is None: 87 | next = next.relativize(origin) 88 | return cls(rdclass, rdtype, next, bitmap) 89 | 90 | from_wire = classmethod(from_wire) 91 | 92 | def choose_relativity(self, origin = None, relativize = True): 93 | self.next = self.next.choose_relativity(origin, relativize) 94 | 95 | def _cmp(self, other): 96 | v = cmp(self.next, other.next) 97 | if v == 0: 98 | v = cmp(self.bitmap, other.bitmap) 99 | return v 100 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/PTR.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.nsbase 17 | 18 | class PTR(dns.rdtypes.nsbase.NSBase): 19 | """PTR record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/RP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.name 19 | 20 | class RP(dns.rdata.Rdata): 21 | """RP record 22 | 23 | @ivar mbox: The responsible person's mailbox 24 | @type mbox: dns.name.Name object 25 | @ivar txt: The owner name of a node with TXT records, or the root name 26 | if no TXT records are associated with this RP. 27 | @type txt: dns.name.Name object 28 | @see: RFC 1183""" 29 | 30 | __slots__ = ['mbox', 'txt'] 31 | 32 | def __init__(self, rdclass, rdtype, mbox, txt): 33 | super(RP, self).__init__(rdclass, rdtype) 34 | self.mbox = mbox 35 | self.txt = txt 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | mbox = self.mbox.choose_relativity(origin, relativize) 39 | txt = self.txt.choose_relativity(origin, relativize) 40 | return "%s %s" % (str(mbox), str(txt)) 41 | 42 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 43 | mbox = tok.get_name() 44 | txt = tok.get_name() 45 | mbox = mbox.choose_relativity(origin, relativize) 46 | txt = txt.choose_relativity(origin, relativize) 47 | tok.get_eol() 48 | return cls(rdclass, rdtype, mbox, txt) 49 | 50 | from_text = classmethod(from_text) 51 | 52 | def to_wire(self, file, compress = None, origin = None): 53 | self.mbox.to_wire(file, None, origin) 54 | self.txt.to_wire(file, None, origin) 55 | 56 | def to_digestable(self, origin = None): 57 | return self.mbox.to_digestable(origin) + \ 58 | self.txt.to_digestable(origin) 59 | 60 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 61 | (mbox, cused) = dns.name.from_wire(wire[: current + rdlen], 62 | current) 63 | current += cused 64 | rdlen -= cused 65 | if rdlen <= 0: 66 | raise dns.exception.FormError 67 | (txt, cused) = dns.name.from_wire(wire[: current + rdlen], 68 | current) 69 | if cused != rdlen: 70 | raise dns.exception.FormError 71 | if not origin is None: 72 | mbox = mbox.relativize(origin) 73 | txt = txt.relativize(origin) 74 | return cls(rdclass, rdtype, mbox, txt) 75 | 76 | from_wire = classmethod(from_wire) 77 | 78 | def choose_relativity(self, origin = None, relativize = True): 79 | self.mbox = self.mbox.choose_relativity(origin, relativize) 80 | self.txt = self.txt.choose_relativity(origin, relativize) 81 | 82 | def _cmp(self, other): 83 | v = cmp(self.mbox, other.mbox) 84 | if v == 0: 85 | v = cmp(self.txt, other.txt) 86 | return v 87 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/RRSIG.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.sigbase 17 | 18 | class RRSIG(dns.rdtypes.sigbase.SIGBase): 19 | """RRSIG record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/RT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.mxbase 17 | 18 | class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX): 19 | """RT record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/SIG.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.sigbase 17 | 18 | class SIG(dns.rdtypes.sigbase.SIGBase): 19 | """SIG record""" 20 | def to_digestable(self, origin = None): 21 | return struct.pack('!HBBIIIH', self.type_covered, 22 | self.algorithm, self.labels, 23 | self.original_ttl, self.expiration, 24 | self.inception, self.key_tag) + \ 25 | self.signer.to_digestable(origin) + \ 26 | self.signature 27 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/SPF.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.txtbase 17 | 18 | class SPF(dns.rdtypes.txtbase.TXTBase): 19 | """SPF record 20 | 21 | @see: RFC 4408""" 22 | pass 23 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/SSHFP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2005-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import struct 17 | 18 | import dns.rdata 19 | import dns.rdatatype 20 | 21 | class SSHFP(dns.rdata.Rdata): 22 | """SSHFP record 23 | 24 | @ivar algorithm: the algorithm 25 | @type algorithm: int 26 | @ivar fp_type: the digest type 27 | @type fp_type: int 28 | @ivar fingerprint: the fingerprint 29 | @type fingerprint: string 30 | @see: draft-ietf-secsh-dns-05.txt""" 31 | 32 | __slots__ = ['algorithm', 'fp_type', 'fingerprint'] 33 | 34 | def __init__(self, rdclass, rdtype, algorithm, fp_type, 35 | fingerprint): 36 | super(SSHFP, self).__init__(rdclass, rdtype) 37 | self.algorithm = algorithm 38 | self.fp_type = fp_type 39 | self.fingerprint = fingerprint 40 | 41 | def to_text(self, origin=None, relativize=True, **kw): 42 | return '%d %d %s' % (self.algorithm, 43 | self.fp_type, 44 | dns.rdata._hexify(self.fingerprint, 45 | chunksize=128)) 46 | 47 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 48 | algorithm = tok.get_uint8() 49 | fp_type = tok.get_uint8() 50 | fingerprint = tok.get_string() 51 | fingerprint = fingerprint.decode('hex_codec') 52 | tok.get_eol() 53 | return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) 54 | 55 | from_text = classmethod(from_text) 56 | 57 | def to_wire(self, file, compress = None, origin = None): 58 | header = struct.pack("!BB", self.algorithm, self.fp_type) 59 | file.write(header) 60 | file.write(self.fingerprint) 61 | 62 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 63 | header = struct.unpack("!BB", wire[current : current + 2]) 64 | current += 2 65 | rdlen -= 2 66 | fingerprint = wire[current : current + rdlen] 67 | return cls(rdclass, rdtype, header[0], header[1], fingerprint) 68 | 69 | from_wire = classmethod(from_wire) 70 | 71 | def _cmp(self, other): 72 | hs = struct.pack("!BB", self.algorithm, self.fp_type) 73 | ho = struct.pack("!BB", other.algorithm, other.fp_type) 74 | v = cmp(hs, ho) 75 | if v == 0: 76 | v = cmp(self.fingerprint, other.fingerprint) 77 | return v 78 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/TXT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.txtbase 17 | 18 | class TXT(dns.rdtypes.txtbase.TXTBase): 19 | """TXT record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/X25.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.tokenizer 19 | 20 | class X25(dns.rdata.Rdata): 21 | """X25 record 22 | 23 | @ivar address: the PSDN address 24 | @type address: string 25 | @see: RFC 1183""" 26 | 27 | __slots__ = ['address'] 28 | 29 | def __init__(self, rdclass, rdtype, address): 30 | super(X25, self).__init__(rdclass, rdtype) 31 | self.address = address 32 | 33 | def to_text(self, origin=None, relativize=True, **kw): 34 | return '"%s"' % dns.rdata._escapify(self.address) 35 | 36 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 37 | address = tok.get_string() 38 | tok.get_eol() 39 | return cls(rdclass, rdtype, address) 40 | 41 | from_text = classmethod(from_text) 42 | 43 | def to_wire(self, file, compress = None, origin = None): 44 | l = len(self.address) 45 | assert l < 256 46 | byte = chr(l) 47 | file.write(byte) 48 | file.write(self.address) 49 | 50 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 51 | l = ord(wire[current]) 52 | current += 1 53 | rdlen -= 1 54 | if l != rdlen: 55 | raise dns.exception.FormError 56 | address = wire[current : current + l] 57 | return cls(rdclass, rdtype, address) 58 | 59 | from_wire = classmethod(from_wire) 60 | 61 | def _cmp(self, other): 62 | return cmp(self.address, other.address) 63 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/ANY/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """Class ANY (generic) rdata type classes.""" 17 | 18 | __all__ = [ 19 | 'AFSDB', 20 | 'CERT', 21 | 'CNAME', 22 | 'DLV', 23 | 'DNAME', 24 | 'DNSKEY', 25 | 'DS', 26 | 'GPOS', 27 | 'HINFO', 28 | 'HIP', 29 | 'ISDN', 30 | 'KEY', 31 | 'LOC', 32 | 'MX', 33 | 'NS', 34 | 'NSEC', 35 | 'NSEC3', 36 | 'NSEC3PARAM', 37 | 'NXT', 38 | 'PTR', 39 | 'RP', 40 | 'RRSIG', 41 | 'RT', 42 | 'SIG', 43 | 'SOA', 44 | 'SPF', 45 | 'SSHFP', 46 | 'TXT', 47 | 'X25', 48 | ] 49 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/A.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.ipv4 18 | import dns.rdata 19 | import dns.tokenizer 20 | 21 | class A(dns.rdata.Rdata): 22 | """A record. 23 | 24 | @ivar address: an IPv4 address 25 | @type address: string (in the standard "dotted quad" format)""" 26 | 27 | __slots__ = ['address'] 28 | 29 | def __init__(self, rdclass, rdtype, address): 30 | super(A, self).__init__(rdclass, rdtype) 31 | # check that it's OK 32 | junk = dns.ipv4.inet_aton(address) 33 | self.address = address 34 | 35 | def to_text(self, origin=None, relativize=True, **kw): 36 | return self.address 37 | 38 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 39 | address = tok.get_identifier() 40 | tok.get_eol() 41 | return cls(rdclass, rdtype, address) 42 | 43 | from_text = classmethod(from_text) 44 | 45 | def to_wire(self, file, compress = None, origin = None): 46 | file.write(dns.ipv4.inet_aton(self.address)) 47 | 48 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 49 | address = dns.ipv4.inet_ntoa(wire[current : current + rdlen]) 50 | return cls(rdclass, rdtype, address) 51 | 52 | from_wire = classmethod(from_wire) 53 | 54 | def _cmp(self, other): 55 | sa = dns.ipv4.inet_aton(self.address) 56 | oa = dns.ipv4.inet_aton(other.address) 57 | return cmp(sa, oa) 58 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/AAAA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.inet 18 | import dns.rdata 19 | import dns.tokenizer 20 | 21 | class AAAA(dns.rdata.Rdata): 22 | """AAAA record. 23 | 24 | @ivar address: an IPv6 address 25 | @type address: string (in the standard IPv6 format)""" 26 | 27 | __slots__ = ['address'] 28 | 29 | def __init__(self, rdclass, rdtype, address): 30 | super(AAAA, self).__init__(rdclass, rdtype) 31 | # check that it's OK 32 | junk = dns.inet.inet_pton(dns.inet.AF_INET6, address) 33 | self.address = address 34 | 35 | def to_text(self, origin=None, relativize=True, **kw): 36 | return self.address 37 | 38 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 39 | address = tok.get_identifier() 40 | tok.get_eol() 41 | return cls(rdclass, rdtype, address) 42 | 43 | from_text = classmethod(from_text) 44 | 45 | def to_wire(self, file, compress = None, origin = None): 46 | file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.address)) 47 | 48 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 49 | address = dns.inet.inet_ntop(dns.inet.AF_INET6, 50 | wire[current : current + rdlen]) 51 | return cls(rdclass, rdtype, address) 52 | 53 | from_wire = classmethod(from_wire) 54 | 55 | def _cmp(self, other): 56 | sa = dns.inet.inet_pton(dns.inet.AF_INET6, self.address) 57 | oa = dns.inet.inet_pton(dns.inet.AF_INET6, other.address) 58 | return cmp(sa, oa) 59 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/DHCID.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | 18 | class DHCID(dns.rdata.Rdata): 19 | """DHCID record 20 | 21 | @ivar data: the data (the content of the RR is opaque as far as the 22 | DNS is concerned) 23 | @type data: string 24 | @see: RFC 4701""" 25 | 26 | __slots__ = ['data'] 27 | 28 | def __init__(self, rdclass, rdtype, data): 29 | super(DHCID, self).__init__(rdclass, rdtype) 30 | self.data = data 31 | 32 | def to_text(self, origin=None, relativize=True, **kw): 33 | return dns.rdata._base64ify(self.data) 34 | 35 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 36 | chunks = [] 37 | while 1: 38 | t = tok.get().unescape() 39 | if t.is_eol_or_eof(): 40 | break 41 | if not t.is_identifier(): 42 | raise dns.exception.SyntaxError 43 | chunks.append(t.value) 44 | b64 = ''.join(chunks) 45 | data = b64.decode('base64_codec') 46 | return cls(rdclass, rdtype, data) 47 | 48 | from_text = classmethod(from_text) 49 | 50 | def to_wire(self, file, compress = None, origin = None): 51 | file.write(self.data) 52 | 53 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 54 | data = wire[current : current + rdlen] 55 | return cls(rdclass, rdtype, data) 56 | 57 | from_wire = classmethod(from_wire) 58 | 59 | def _cmp(self, other): 60 | return cmp(self.data, other.data) 61 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/KX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.mxbase 17 | 18 | class KX(dns.rdtypes.mxbase.UncompressedMX): 19 | """KX record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/NSAP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.exception 17 | import dns.rdata 18 | import dns.tokenizer 19 | 20 | class NSAP(dns.rdata.Rdata): 21 | """NSAP record. 22 | 23 | @ivar address: a NASP 24 | @type address: string 25 | @see: RFC 1706""" 26 | 27 | __slots__ = ['address'] 28 | 29 | def __init__(self, rdclass, rdtype, address): 30 | super(NSAP, self).__init__(rdclass, rdtype) 31 | self.address = address 32 | 33 | def to_text(self, origin=None, relativize=True, **kw): 34 | return "0x%s" % self.address.encode('hex_codec') 35 | 36 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 37 | address = tok.get_string() 38 | t = tok.get_eol() 39 | if address[0:2] != '0x': 40 | raise dns.exception.SyntaxError('string does not start with 0x') 41 | address = address[2:].replace('.', '') 42 | if len(address) % 2 != 0: 43 | raise dns.exception.SyntaxError('hexstring has odd length') 44 | address = address.decode('hex_codec') 45 | return cls(rdclass, rdtype, address) 46 | 47 | from_text = classmethod(from_text) 48 | 49 | def to_wire(self, file, compress = None, origin = None): 50 | file.write(self.address) 51 | 52 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 53 | address = wire[current : current + rdlen] 54 | return cls(rdclass, rdtype, address) 55 | 56 | from_wire = classmethod(from_wire) 57 | 58 | def _cmp(self, other): 59 | return cmp(self.address, other.address) 60 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/NSAP_PTR.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import dns.rdtypes.nsbase 17 | 18 | class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS): 19 | """NSAP-PTR record""" 20 | pass 21 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/PX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import struct 17 | 18 | import dns.exception 19 | import dns.rdata 20 | import dns.name 21 | 22 | class PX(dns.rdata.Rdata): 23 | """PX record. 24 | 25 | @ivar preference: the preference value 26 | @type preference: int 27 | @ivar map822: the map822 name 28 | @type map822: dns.name.Name object 29 | @ivar mapx400: the mapx400 name 30 | @type mapx400: dns.name.Name object 31 | @see: RFC 2163""" 32 | 33 | __slots__ = ['preference', 'map822', 'mapx400'] 34 | 35 | def __init__(self, rdclass, rdtype, preference, map822, mapx400): 36 | super(PX, self).__init__(rdclass, rdtype) 37 | self.preference = preference 38 | self.map822 = map822 39 | self.mapx400 = mapx400 40 | 41 | def to_text(self, origin=None, relativize=True, **kw): 42 | map822 = self.map822.choose_relativity(origin, relativize) 43 | mapx400 = self.mapx400.choose_relativity(origin, relativize) 44 | return '%d %s %s' % (self.preference, map822, mapx400) 45 | 46 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 47 | preference = tok.get_uint16() 48 | map822 = tok.get_name() 49 | map822 = map822.choose_relativity(origin, relativize) 50 | mapx400 = tok.get_name(None) 51 | mapx400 = mapx400.choose_relativity(origin, relativize) 52 | tok.get_eol() 53 | return cls(rdclass, rdtype, preference, map822, mapx400) 54 | 55 | from_text = classmethod(from_text) 56 | 57 | def to_wire(self, file, compress = None, origin = None): 58 | pref = struct.pack("!H", self.preference) 59 | file.write(pref) 60 | self.map822.to_wire(file, None, origin) 61 | self.mapx400.to_wire(file, None, origin) 62 | 63 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 64 | (preference, ) = struct.unpack('!H', wire[current : current + 2]) 65 | current += 2 66 | rdlen -= 2 67 | (map822, cused) = dns.name.from_wire(wire[: current + rdlen], 68 | current) 69 | if cused > rdlen: 70 | raise dns.exception.FormError 71 | current += cused 72 | rdlen -= cused 73 | if not origin is None: 74 | map822 = map822.relativize(origin) 75 | (mapx400, cused) = dns.name.from_wire(wire[: current + rdlen], 76 | current) 77 | if cused != rdlen: 78 | raise dns.exception.FormError 79 | if not origin is None: 80 | mapx400 = mapx400.relativize(origin) 81 | return cls(rdclass, rdtype, preference, map822, mapx400) 82 | 83 | from_wire = classmethod(from_wire) 84 | 85 | def choose_relativity(self, origin = None, relativize = True): 86 | self.map822 = self.map822.choose_relativity(origin, relativize) 87 | self.mapx400 = self.mapx400.choose_relativity(origin, relativize) 88 | 89 | def _cmp(self, other): 90 | sp = struct.pack("!H", self.preference) 91 | op = struct.pack("!H", other.preference) 92 | v = cmp(sp, op) 93 | if v == 0: 94 | v = cmp(self.map822, other.map822) 95 | if v == 0: 96 | v = cmp(self.mapx400, other.mapx400) 97 | return v 98 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/SRV.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import struct 17 | 18 | import dns.exception 19 | import dns.rdata 20 | import dns.name 21 | 22 | class SRV(dns.rdata.Rdata): 23 | """SRV record 24 | 25 | @ivar priority: the priority 26 | @type priority: int 27 | @ivar weight: the weight 28 | @type weight: int 29 | @ivar port: the port of the service 30 | @type port: int 31 | @ivar target: the target host 32 | @type target: dns.name.Name object 33 | @see: RFC 2782""" 34 | 35 | __slots__ = ['priority', 'weight', 'port', 'target'] 36 | 37 | def __init__(self, rdclass, rdtype, priority, weight, port, target): 38 | super(SRV, self).__init__(rdclass, rdtype) 39 | self.priority = priority 40 | self.weight = weight 41 | self.port = port 42 | self.target = target 43 | 44 | def to_text(self, origin=None, relativize=True, **kw): 45 | target = self.target.choose_relativity(origin, relativize) 46 | return '%d %d %d %s' % (self.priority, self.weight, self.port, 47 | target) 48 | 49 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 50 | priority = tok.get_uint16() 51 | weight = tok.get_uint16() 52 | port = tok.get_uint16() 53 | target = tok.get_name(None) 54 | target = target.choose_relativity(origin, relativize) 55 | tok.get_eol() 56 | return cls(rdclass, rdtype, priority, weight, port, target) 57 | 58 | from_text = classmethod(from_text) 59 | 60 | def to_wire(self, file, compress = None, origin = None): 61 | three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) 62 | file.write(three_ints) 63 | self.target.to_wire(file, compress, origin) 64 | 65 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 66 | (priority, weight, port) = struct.unpack('!HHH', 67 | wire[current : current + 6]) 68 | current += 6 69 | rdlen -= 6 70 | (target, cused) = dns.name.from_wire(wire[: current + rdlen], 71 | current) 72 | if cused != rdlen: 73 | raise dns.exception.FormError 74 | if not origin is None: 75 | target = target.relativize(origin) 76 | return cls(rdclass, rdtype, priority, weight, port, target) 77 | 78 | from_wire = classmethod(from_wire) 79 | 80 | def choose_relativity(self, origin = None, relativize = True): 81 | self.target = self.target.choose_relativity(origin, relativize) 82 | 83 | def _cmp(self, other): 84 | sp = struct.pack("!HHH", self.priority, self.weight, self.port) 85 | op = struct.pack("!HHH", other.priority, other.weight, other.port) 86 | v = cmp(sp, op) 87 | if v == 0: 88 | v = cmp(self.target, other.target) 89 | return v 90 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/WKS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import socket 17 | import struct 18 | 19 | import dns.ipv4 20 | import dns.rdata 21 | 22 | _proto_tcp = socket.getprotobyname('tcp') 23 | _proto_udp = socket.getprotobyname('udp') 24 | 25 | class WKS(dns.rdata.Rdata): 26 | """WKS record 27 | 28 | @ivar address: the address 29 | @type address: string 30 | @ivar protocol: the protocol 31 | @type protocol: int 32 | @ivar bitmap: the bitmap 33 | @type bitmap: string 34 | @see: RFC 1035""" 35 | 36 | __slots__ = ['address', 'protocol', 'bitmap'] 37 | 38 | def __init__(self, rdclass, rdtype, address, protocol, bitmap): 39 | super(WKS, self).__init__(rdclass, rdtype) 40 | self.address = address 41 | self.protocol = protocol 42 | self.bitmap = bitmap 43 | 44 | def to_text(self, origin=None, relativize=True, **kw): 45 | bits = [] 46 | for i in xrange(0, len(self.bitmap)): 47 | byte = ord(self.bitmap[i]) 48 | for j in xrange(0, 8): 49 | if byte & (0x80 >> j): 50 | bits.append(str(i * 8 + j)) 51 | text = ' '.join(bits) 52 | return '%s %d %s' % (self.address, self.protocol, text) 53 | 54 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 55 | address = tok.get_string() 56 | protocol = tok.get_string() 57 | if protocol.isdigit(): 58 | protocol = int(protocol) 59 | else: 60 | protocol = socket.getprotobyname(protocol) 61 | bitmap = [] 62 | while 1: 63 | token = tok.get().unescape() 64 | if token.is_eol_or_eof(): 65 | break 66 | if token.value.isdigit(): 67 | serv = int(token.value) 68 | else: 69 | if protocol != _proto_udp and protocol != _proto_tcp: 70 | raise NotImplementedError("protocol must be TCP or UDP") 71 | if protocol == _proto_udp: 72 | protocol_text = "udp" 73 | else: 74 | protocol_text = "tcp" 75 | serv = socket.getservbyname(token.value, protocol_text) 76 | i = serv // 8 77 | l = len(bitmap) 78 | if l < i + 1: 79 | for j in xrange(l, i + 1): 80 | bitmap.append('\x00') 81 | bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (serv % 8))) 82 | bitmap = dns.rdata._truncate_bitmap(bitmap) 83 | return cls(rdclass, rdtype, address, protocol, bitmap) 84 | 85 | from_text = classmethod(from_text) 86 | 87 | def to_wire(self, file, compress = None, origin = None): 88 | file.write(dns.ipv4.inet_aton(self.address)) 89 | protocol = struct.pack('!B', self.protocol) 90 | file.write(protocol) 91 | file.write(self.bitmap) 92 | 93 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 94 | address = dns.ipv4.inet_ntoa(wire[current : current + 4]) 95 | protocol, = struct.unpack('!B', wire[current + 4 : current + 5]) 96 | current += 5 97 | rdlen -= 5 98 | bitmap = wire[current : current + rdlen] 99 | return cls(rdclass, rdtype, address, protocol, bitmap) 100 | 101 | from_wire = classmethod(from_wire) 102 | 103 | def _cmp(self, other): 104 | sa = dns.ipv4.inet_aton(self.address) 105 | oa = dns.ipv4.inet_aton(other.address) 106 | v = cmp(sa, oa) 107 | if v == 0: 108 | sp = struct.pack('!B', self.protocol) 109 | op = struct.pack('!B', other.protocol) 110 | v = cmp(sp, op) 111 | if v == 0: 112 | v = cmp(self.bitmap, other.bitmap) 113 | return v 114 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/IN/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """Class IN rdata type classes.""" 17 | 18 | __all__ = [ 19 | 'A', 20 | 'AAAA', 21 | 'APL', 22 | 'DHCID', 23 | 'KX', 24 | 'NAPTR', 25 | 'NSAP', 26 | 'NSAP_PTR', 27 | 'PX', 28 | 'SRV', 29 | 'WKS', 30 | ] 31 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS rdata type classes""" 17 | 18 | __all__ = [ 19 | 'ANY', 20 | 'IN', 21 | 'mxbase', 22 | 'nsbase', 23 | 'sigbase', 24 | 'keybase', 25 | ] 26 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/dsbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import struct 17 | 18 | import dns.rdata 19 | import dns.rdatatype 20 | 21 | class DSBase(dns.rdata.Rdata): 22 | """Base class for rdata that is like a DS record 23 | 24 | @ivar key_tag: the key tag 25 | @type key_tag: int 26 | @ivar algorithm: the algorithm 27 | @type algorithm: int 28 | @ivar digest_type: the digest type 29 | @type digest_type: int 30 | @ivar digest: the digest 31 | @type digest: int 32 | @see: draft-ietf-dnsext-delegation-signer-14.txt""" 33 | 34 | __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest'] 35 | 36 | def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, 37 | digest): 38 | super(DSBase, self).__init__(rdclass, rdtype) 39 | self.key_tag = key_tag 40 | self.algorithm = algorithm 41 | self.digest_type = digest_type 42 | self.digest = digest 43 | 44 | def to_text(self, origin=None, relativize=True, **kw): 45 | return '%d %d %d %s' % (self.key_tag, self.algorithm, 46 | self.digest_type, 47 | dns.rdata._hexify(self.digest, 48 | chunksize=128)) 49 | 50 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 51 | key_tag = tok.get_uint16() 52 | algorithm = tok.get_uint8() 53 | digest_type = tok.get_uint8() 54 | chunks = [] 55 | while 1: 56 | t = tok.get().unescape() 57 | if t.is_eol_or_eof(): 58 | break 59 | if not t.is_identifier(): 60 | raise dns.exception.SyntaxError 61 | chunks.append(t.value) 62 | digest = ''.join(chunks) 63 | digest = digest.decode('hex_codec') 64 | return cls(rdclass, rdtype, key_tag, algorithm, digest_type, 65 | digest) 66 | 67 | from_text = classmethod(from_text) 68 | 69 | def to_wire(self, file, compress = None, origin = None): 70 | header = struct.pack("!HBB", self.key_tag, self.algorithm, 71 | self.digest_type) 72 | file.write(header) 73 | file.write(self.digest) 74 | 75 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 76 | header = struct.unpack("!HBB", wire[current : current + 4]) 77 | current += 4 78 | rdlen -= 4 79 | digest = wire[current : current + rdlen] 80 | return cls(rdclass, rdtype, header[0], header[1], header[2], digest) 81 | 82 | from_wire = classmethod(from_wire) 83 | 84 | def _cmp(self, other): 85 | hs = struct.pack("!HBB", self.key_tag, self.algorithm, 86 | self.digest_type) 87 | ho = struct.pack("!HBB", other.key_tag, other.algorithm, 88 | other.digest_type) 89 | v = cmp(hs, ho) 90 | if v == 0: 91 | v = cmp(self.digest, other.digest) 92 | return v 93 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/mxbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """MX-like base classes.""" 17 | 18 | import cStringIO 19 | import struct 20 | 21 | import dns.exception 22 | import dns.rdata 23 | import dns.name 24 | 25 | class MXBase(dns.rdata.Rdata): 26 | """Base class for rdata that is like an MX record. 27 | 28 | @ivar preference: the preference value 29 | @type preference: int 30 | @ivar exchange: the exchange name 31 | @type exchange: dns.name.Name object""" 32 | 33 | __slots__ = ['preference', 'exchange'] 34 | 35 | def __init__(self, rdclass, rdtype, preference, exchange): 36 | super(MXBase, self).__init__(rdclass, rdtype) 37 | self.preference = preference 38 | self.exchange = exchange 39 | 40 | def to_text(self, origin=None, relativize=True, **kw): 41 | exchange = self.exchange.choose_relativity(origin, relativize) 42 | return '%d %s' % (self.preference, exchange) 43 | 44 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 45 | preference = tok.get_uint16() 46 | exchange = tok.get_name() 47 | exchange = exchange.choose_relativity(origin, relativize) 48 | tok.get_eol() 49 | return cls(rdclass, rdtype, preference, exchange) 50 | 51 | from_text = classmethod(from_text) 52 | 53 | def to_wire(self, file, compress = None, origin = None): 54 | pref = struct.pack("!H", self.preference) 55 | file.write(pref) 56 | self.exchange.to_wire(file, compress, origin) 57 | 58 | def to_digestable(self, origin = None): 59 | return struct.pack("!H", self.preference) + \ 60 | self.exchange.to_digestable(origin) 61 | 62 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 63 | (preference, ) = struct.unpack('!H', wire[current : current + 2]) 64 | current += 2 65 | rdlen -= 2 66 | (exchange, cused) = dns.name.from_wire(wire[: current + rdlen], 67 | current) 68 | if cused != rdlen: 69 | raise dns.exception.FormError 70 | if not origin is None: 71 | exchange = exchange.relativize(origin) 72 | return cls(rdclass, rdtype, preference, exchange) 73 | 74 | from_wire = classmethod(from_wire) 75 | 76 | def choose_relativity(self, origin = None, relativize = True): 77 | self.exchange = self.exchange.choose_relativity(origin, relativize) 78 | 79 | def _cmp(self, other): 80 | sp = struct.pack("!H", self.preference) 81 | op = struct.pack("!H", other.preference) 82 | v = cmp(sp, op) 83 | if v == 0: 84 | v = cmp(self.exchange, other.exchange) 85 | return v 86 | 87 | class UncompressedMX(MXBase): 88 | """Base class for rdata that is like an MX record, but whose name 89 | is not compressed when converted to DNS wire format, and whose 90 | digestable form is not downcased.""" 91 | 92 | def to_wire(self, file, compress = None, origin = None): 93 | super(UncompressedMX, self).to_wire(file, None, origin) 94 | 95 | def to_digestable(self, origin = None): 96 | f = cStringIO.StringIO() 97 | self.to_wire(f, None, origin) 98 | return f.getvalue() 99 | 100 | class UncompressedDowncasingMX(MXBase): 101 | """Base class for rdata that is like an MX record, but whose name 102 | is not compressed when convert to DNS wire format.""" 103 | 104 | def to_wire(self, file, compress = None, origin = None): 105 | super(UncompressedDowncasingMX, self).to_wire(file, None, origin) 106 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/nsbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """NS-like base classes.""" 17 | 18 | import cStringIO 19 | 20 | import dns.exception 21 | import dns.rdata 22 | import dns.name 23 | 24 | class NSBase(dns.rdata.Rdata): 25 | """Base class for rdata that is like an NS record. 26 | 27 | @ivar target: the target name of the rdata 28 | @type target: dns.name.Name object""" 29 | 30 | __slots__ = ['target'] 31 | 32 | def __init__(self, rdclass, rdtype, target): 33 | super(NSBase, self).__init__(rdclass, rdtype) 34 | self.target = target 35 | 36 | def to_text(self, origin=None, relativize=True, **kw): 37 | target = self.target.choose_relativity(origin, relativize) 38 | return str(target) 39 | 40 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 41 | target = tok.get_name() 42 | target = target.choose_relativity(origin, relativize) 43 | tok.get_eol() 44 | return cls(rdclass, rdtype, target) 45 | 46 | from_text = classmethod(from_text) 47 | 48 | def to_wire(self, file, compress = None, origin = None): 49 | self.target.to_wire(file, compress, origin) 50 | 51 | def to_digestable(self, origin = None): 52 | return self.target.to_digestable(origin) 53 | 54 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 55 | (target, cused) = dns.name.from_wire(wire[: current + rdlen], 56 | current) 57 | if cused != rdlen: 58 | raise dns.exception.FormError 59 | if not origin is None: 60 | target = target.relativize(origin) 61 | return cls(rdclass, rdtype, target) 62 | 63 | from_wire = classmethod(from_wire) 64 | 65 | def choose_relativity(self, origin = None, relativize = True): 66 | self.target = self.target.choose_relativity(origin, relativize) 67 | 68 | def _cmp(self, other): 69 | return cmp(self.target, other.target) 70 | 71 | class UncompressedNS(NSBase): 72 | """Base class for rdata that is like an NS record, but whose name 73 | is not compressed when convert to DNS wire format, and whose 74 | digestable form is not downcased.""" 75 | 76 | def to_wire(self, file, compress = None, origin = None): 77 | super(UncompressedNS, self).to_wire(file, None, origin) 78 | 79 | def to_digestable(self, origin = None): 80 | f = cStringIO.StringIO() 81 | self.to_wire(f, None, origin) 82 | return f.getvalue() 83 | -------------------------------------------------------------------------------- /third_party/dns/rdtypes/txtbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """TXT-like base class.""" 17 | 18 | import dns.exception 19 | import dns.rdata 20 | import dns.tokenizer 21 | 22 | class TXTBase(dns.rdata.Rdata): 23 | """Base class for rdata that is like a TXT record 24 | 25 | @ivar strings: the text strings 26 | @type strings: list of string 27 | @see: RFC 1035""" 28 | 29 | __slots__ = ['strings'] 30 | 31 | def __init__(self, rdclass, rdtype, strings): 32 | super(TXTBase, self).__init__(rdclass, rdtype) 33 | if isinstance(strings, str): 34 | strings = [ strings ] 35 | self.strings = strings[:] 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | txt = '' 39 | prefix = '' 40 | for s in self.strings: 41 | txt += '%s"%s"' % (prefix, dns.rdata._escapify(s)) 42 | prefix = ' ' 43 | return txt 44 | 45 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 46 | strings = [] 47 | while 1: 48 | token = tok.get().unescape() 49 | if token.is_eol_or_eof(): 50 | break 51 | if not (token.is_quoted_string() or token.is_identifier()): 52 | raise dns.exception.SyntaxError("expected a string") 53 | if len(token.value) > 255: 54 | raise dns.exception.SyntaxError("string too long") 55 | strings.append(token.value) 56 | if len(strings) == 0: 57 | raise dns.exception.UnexpectedEnd 58 | return cls(rdclass, rdtype, strings) 59 | 60 | from_text = classmethod(from_text) 61 | 62 | def to_wire(self, file, compress = None, origin = None): 63 | for s in self.strings: 64 | l = len(s) 65 | assert l < 256 66 | byte = chr(l) 67 | file.write(byte) 68 | file.write(s) 69 | 70 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 71 | strings = [] 72 | while rdlen > 0: 73 | l = ord(wire[current]) 74 | current += 1 75 | rdlen -= 1 76 | if l > rdlen: 77 | raise dns.exception.FormError 78 | s = wire[current : current + l] 79 | current += l 80 | rdlen -= l 81 | strings.append(s) 82 | return cls(rdclass, rdtype, strings) 83 | 84 | from_wire = classmethod(from_wire) 85 | 86 | def _cmp(self, other): 87 | return cmp(self.strings, other.strings) 88 | -------------------------------------------------------------------------------- /third_party/dns/reversename.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS Reverse Map Names. 17 | 18 | @var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa. 19 | @type ipv4_reverse_domain: dns.name.Name object 20 | @var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa. 21 | @type ipv6_reverse_domain: dns.name.Name object 22 | """ 23 | 24 | import dns.name 25 | import dns.ipv6 26 | import dns.ipv4 27 | 28 | ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.') 29 | ipv6_reverse_domain = dns.name.from_text('ip6.arpa.') 30 | 31 | def from_address(text): 32 | """Convert an IPv4 or IPv6 address in textual form into a Name object whose 33 | value is the reverse-map domain name of the address. 34 | @param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1', 35 | '::1') 36 | @type text: str 37 | @rtype: dns.name.Name object 38 | """ 39 | try: 40 | parts = list(dns.ipv6.inet_aton(text).encode('hex_codec')) 41 | origin = ipv6_reverse_domain 42 | except: 43 | parts = ['%d' % ord(byte) for byte in dns.ipv4.inet_aton(text)] 44 | origin = ipv4_reverse_domain 45 | parts.reverse() 46 | return dns.name.from_text('.'.join(parts), origin=origin) 47 | 48 | def to_address(name): 49 | """Convert a reverse map domain name into textual address form. 50 | @param name: an IPv4 or IPv6 address in reverse-map form. 51 | @type name: dns.name.Name object 52 | @rtype: str 53 | """ 54 | if name.is_subdomain(ipv4_reverse_domain): 55 | name = name.relativize(ipv4_reverse_domain) 56 | labels = list(name.labels) 57 | labels.reverse() 58 | text = '.'.join(labels) 59 | # run through inet_aton() to check syntax and make pretty. 60 | return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) 61 | elif name.is_subdomain(ipv6_reverse_domain): 62 | name = name.relativize(ipv6_reverse_domain) 63 | labels = list(name.labels) 64 | labels.reverse() 65 | parts = [] 66 | i = 0 67 | l = len(labels) 68 | while i < l: 69 | parts.append(''.join(labels[i:i+4])) 70 | i += 4 71 | text = ':'.join(parts) 72 | # run through inet_aton() to check syntax and make pretty. 73 | return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) 74 | else: 75 | raise dns.exception.SyntaxError('unknown reverse-map address family') 76 | -------------------------------------------------------------------------------- /third_party/dns/tsigkeyring.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """A place to store TSIG keys.""" 17 | 18 | import base64 19 | 20 | import dns.name 21 | 22 | def from_text(textring): 23 | """Convert a dictionary containing (textual DNS name, base64 secret) pairs 24 | into a binary keyring which has (dns.name.Name, binary secret) pairs. 25 | @rtype: dict""" 26 | 27 | keyring = {} 28 | for keytext in textring: 29 | keyname = dns.name.from_text(keytext) 30 | secret = base64.decodestring(textring[keytext]) 31 | keyring[keyname] = secret 32 | return keyring 33 | 34 | def to_text(keyring): 35 | """Convert a dictionary containing (dns.name.Name, binary secret) pairs 36 | into a text keyring which has (textual DNS name, base64 secret) pairs. 37 | @rtype: dict""" 38 | 39 | textring = {} 40 | for keyname in keyring: 41 | keytext = dns.name.to_text(keyname) 42 | secret = base64.encodestring(keyring[keyname]) 43 | textring[keytext] = secret 44 | return textring 45 | -------------------------------------------------------------------------------- /third_party/dns/ttl.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """DNS TTL conversion.""" 17 | 18 | import dns.exception 19 | 20 | class BadTTL(dns.exception.SyntaxError): 21 | pass 22 | 23 | def from_text(text): 24 | """Convert the text form of a TTL to an integer. 25 | 26 | The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported. 27 | 28 | @param text: the textual TTL 29 | @type text: string 30 | @raises dns.ttl.BadTTL: the TTL is not well-formed 31 | @rtype: int 32 | """ 33 | 34 | if text.isdigit(): 35 | total = long(text) 36 | else: 37 | if not text[0].isdigit(): 38 | raise BadTTL 39 | total = 0L 40 | current = 0L 41 | for c in text: 42 | if c.isdigit(): 43 | current *= 10 44 | current += long(c) 45 | else: 46 | c = c.lower() 47 | if c == 'w': 48 | total += current * 604800L 49 | elif c == 'd': 50 | total += current * 86400L 51 | elif c == 'h': 52 | total += current * 3600L 53 | elif c == 'm': 54 | total += current * 60L 55 | elif c == 's': 56 | total += current 57 | else: 58 | raise BadTTL("unknown unit '%s'" % c) 59 | current = 0 60 | if not current == 0: 61 | raise BadTTL("trailing integer") 62 | if total < 0L or total > 2147483647L: 63 | raise BadTTL("TTL should be between 0 and 2^31 - 1 (inclusive)") 64 | return total 65 | -------------------------------------------------------------------------------- /third_party/dns/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. 2 | # 3 | # Permission to use, copy, modify, and distribute this software and its 4 | # documentation for any purpose with or without fee is hereby granted, 5 | # provided that the above copyright notice and this permission notice 6 | # appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | """dnspython release version information.""" 17 | 18 | MAJOR = 1 19 | MINOR = 8 20 | MICRO = 0 21 | RELEASELEVEL = 0x0f 22 | SERIAL = 0 23 | 24 | if RELEASELEVEL == 0x0f: 25 | version = '%d.%d.%d' % (MAJOR, MINOR, MICRO) 26 | elif RELEASELEVEL == 0x00: 27 | version = '%d.%d.%dx%d' % \ 28 | (MAJOR, MINOR, MICRO, SERIAL) 29 | else: 30 | version = '%d.%d.%d%x%d' % \ 31 | (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL) 32 | 33 | hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \ 34 | SERIAL 35 | -------------------------------------------------------------------------------- /third_party/ipaddr/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING 2 | include ipaddr_test.py 3 | include RELEASENOTES 4 | -------------------------------------------------------------------------------- /third_party/ipaddr/OWNERS: -------------------------------------------------------------------------------- 1 | pmoody 2 | harro 3 | mshields 4 | smart 5 | -------------------------------------------------------------------------------- /third_party/ipaddr/README: -------------------------------------------------------------------------------- 1 | ipaddr.py is a library for working with IP addresses, both IPv4 and IPv6. 2 | It was developed by Google for internal use, and is now open source. 3 | 4 | Project home page: http://code.google.com/p/ipaddr-py/ 5 | 6 | Please send contributions to ipaddr-py-dev@googlegroups.com. Code should 7 | include unit tests and follow the Google Python style guide: 8 | http://code.google.com/p/soc/wiki/PythonStyleGuide 9 | -------------------------------------------------------------------------------- /third_party/ipaddr/README.web-page-replay: -------------------------------------------------------------------------------- 1 | Name: An IPv4/IPv6 manipulation library in Python. 2 | Short Name: ipaddr-py 3 | URL: https://code.google.com/p/ipaddr-py/ 4 | Version: 2.1.10 (ipaddr.__version__) 5 | License: Apache (v2.0) 6 | License File: COPYING 7 | 8 | Description: 9 | Used by Web Page Replay to check if an IP address is private. 10 | 11 | Local Modifications: 12 | Cherry picked revision 728996d6b1d4 to add license boilerplate to test-2to3.sh. 13 | -------------------------------------------------------------------------------- /third_party/ipaddr/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright 2008 Google Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from distutils.core import setup 18 | 19 | import ipaddr 20 | 21 | 22 | setup(name='ipaddr', 23 | maintainer='Google', 24 | maintainer_email='ipaddr-py-dev@googlegroups.com', 25 | version=ipaddr.__version__, 26 | url='http://code.google.com/p/ipaddr-py/', 27 | license='Apache License, Version 2.0', 28 | classifiers=[ 29 | 'Development Status :: 5 - Production/Stable', 30 | 'Intended Audience :: Developers', 31 | 'License :: OSI Approved :: Apache Software License', 32 | 'Operating System :: OS Independent', 33 | 'Topic :: Internet', 34 | 'Topic :: Software Development :: Libraries', 35 | 'Topic :: System :: Networking'], 36 | py_modules=['ipaddr']) 37 | -------------------------------------------------------------------------------- /third_party/ipaddr/test-2to3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2007 Google Inc. 3 | # Licensed to PSF under a Contributor Agreement. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 14 | # implied. See the License for the specific language governing 15 | # permissions and limitations under the License. 16 | # 17 | # Converts the python2 ipaddr files to python3 and runs the unit tests 18 | # with both python versions. 19 | 20 | mkdir -p 2to3output && \ 21 | cp -f *.py 2to3output && \ 22 | ( cd 2to3output && 2to3 . | patch -p0 ) && \ 23 | py3version=$(python3 --version 2>&1) && \ 24 | echo -e "\nTesting with ${py3version}" && \ 25 | python3 2to3output/ipaddr_test.py && \ 26 | rm -r 2to3output && \ 27 | pyversion=$(python --version 2>&1) && \ 28 | echo -e "\nTesting with ${pyversion}" && \ 29 | ./ipaddr_test.py 30 | -------------------------------------------------------------------------------- /third_party/ipfw_win32/LICENSE: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1998-2010 Luigi Rizzo, Universita` di Pisa 3 | * All rights reserved 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | -------------------------------------------------------------------------------- /third_party/ipfw_win32/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains the binaries to install and use IPFW and 2 | DUMMYNET on a Windows Machine. The kernel part is an NDIS module, 3 | whereas the user interface is a command line program. 4 | 5 | 1. INSTALL THE NDIS DRIVER 6 | 7 | - open the configuration panel for the network card in use 8 | (either right click on the icon on the SYSTRAY, or go to 9 | Control Panel -> Network and select one card) 10 | 11 | - click on Properties->Install->Service->Add 12 | - click on 'Driver Disk' and select 'netipfw.inf' in this folder 13 | - select 'ipfw+dummynet' which is the only service you should see 14 | - click accept on the warnings for the installation of an unknown 15 | driver (roughly twice per existing network card) 16 | 17 | Now you are ready to use the emulator. To configure it, open a 'cmd' 18 | window and you can use the ipfw command from the command line. 19 | Otherwise click on the 'TESTME.bat' which is a batch program that 20 | runs various tests. 21 | 22 | 2. UNINSTALL THE DRIVER 23 | 24 | - select a network card as above. 25 | - click on Properties 26 | - select 'ipfw+dummynet' 27 | - click on 'Remove' 28 | -------------------------------------------------------------------------------- /third_party/ipfw_win32/README.web-page-replay: -------------------------------------------------------------------------------- 1 | Name: Windows XP NDIS module for Dummynet. 2 | Short Name: ipfw3 3 | URL: http://info.iet.unipi.it/~luigi/dummynet/ 4 | Version: 20100322 v.3.0.0.2 5 | License: BSD 6 | License File: LICENSE 7 | 8 | Description: 9 | Used by Web Page Replay to simulate network delays and bandwidth throttling on Windows XP. 10 | 11 | Local Modifications: 12 | Dropped files: cyg-ipfw.exe, cygwin1.dll, testme.bat, wget.exe. -------------------------------------------------------------------------------- /third_party/ipfw_win32/ipfw.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chromium/web-page-replay/472351e1122bb1beb936952c7e75ae58bf8a69f1/third_party/ipfw_win32/ipfw.exe -------------------------------------------------------------------------------- /third_party/ipfw_win32/ipfw.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chromium/web-page-replay/472351e1122bb1beb936952c7e75ae58bf8a69f1/third_party/ipfw_win32/ipfw.sys -------------------------------------------------------------------------------- /third_party/ipfw_win32/netipfw.inf: -------------------------------------------------------------------------------- 1 | ; version section 2 | [Version] 3 | Signature = "$Windows NT$" 4 | Class = NetService 5 | ClassGUID = {4D36E974-E325-11CE-BFC1-08002BE10318} 6 | Provider = %Unipi% 7 | DriverVer = 26/02/2010,3.0.0.2 8 | 9 | ; manufacturer section 10 | [Manufacturer] 11 | %Unipi% = UNIPI,NTx86 12 | 13 | ; control flags section 14 | ; optional, unused in netipfw.inf inf, used in netipfw_m.inf 15 | [ControlFlags] 16 | 17 | ; models section 18 | [UNIPI] ; Win2k 19 | %Desc% = Ipfw.ndi, unipi_ipfw 20 | [UNIPI.NTx86] ;For WinXP and later 21 | %Desc% = Ipfw.ndi, unipi_ipfw 22 | 23 | ; ddinstall section 24 | [Ipfw.ndi] 25 | AddReg = Ipfw.ndi.AddReg, Ipfw.AddReg 26 | Characteristics = 0x4410 ; NCF_FILTER | NCF_NDIS_PROTOCOL !--Filter Specific--!! 27 | CopyFiles = Ipfw.Files.Sys 28 | CopyInf = netipfw_m.inf 29 | 30 | ; remove section 31 | [Ipfw.ndi.Remove] 32 | DelFiles = Ipfw.Files.Sys 33 | 34 | ;ddinstall.services section 35 | [Ipfw.ndi.Services] 36 | AddService = Ipfw,,Ipfw.AddService 37 | 38 | [Ipfw.AddService] 39 | DisplayName = %ServiceDesc% 40 | ServiceType = 1 ;SERVICE_KERNEL_DRIVER 41 | StartType = 3 ;SERVICE_DEMAND_START 42 | ErrorControl = 1 ;SERVICE_ERROR_NORMAL 43 | ServiceBinary = %12%\ipfw.sys 44 | AddReg = Ipfw.AddService.AddReg 45 | 46 | [Ipfw.AddService.AddReg] 47 | 48 | ;file copy related sections 49 | [SourceDisksNames] 50 | 1=%DiskDescription%,"",, 51 | 52 | [SourceDisksFiles] 53 | ipfw.sys=1 54 | 55 | [DestinationDirs] 56 | DefaultDestDir = 12 57 | Ipfw.Files.Sys = 12 ; %windir%\System32\drivers 58 | 59 | ; ddinstall->copyfiles points here 60 | [Ipfw.Files.Sys] 61 | ipfw.sys,,,2 62 | 63 | ; ddinstall->addreg points here 64 | [Ipfw.ndi.AddReg] 65 | HKR, Ndi, HelpText, , %HELP% ; this is displayed at the bottom of the General page of the Connection Properties dialog box 66 | HKR, Ndi, FilterClass, , failover 67 | HKR, Ndi, FilterDeviceInfId, , unipi_ipfwmp 68 | HKR, Ndi, Service, , Ipfw 69 | HKR, Ndi\Interfaces, UpperRange, , noupper 70 | HKR, Ndi\Interfaces, LowerRange, , nolower 71 | HKR, Ndi\Interfaces, FilterMediaTypes, , "ethernet, tokenring, fddi, wan" 72 | 73 | ;strings section 74 | [Strings] 75 | Unipi = "Unipi" 76 | DiskDescription = "Ipfw Driver Disk" 77 | Desc = "ipfw+dummynet" 78 | HELP = "This is ipfw and dummynet network emulator, developed by unipi.it" 79 | ServiceDesc = "ipfw service" 80 | -------------------------------------------------------------------------------- /third_party/ipfw_win32/netipfw_m.inf: -------------------------------------------------------------------------------- 1 | ; version section 2 | [Version] 3 | Signature = "$Windows NT$" 4 | Class = Net 5 | ClassGUID = {4D36E972-E325-11CE-BFC1-08002BE10318} 6 | Provider = %Unipi% 7 | DriverVer = 26/02/2010,3.0.0.2 8 | 9 | ; control flags section 10 | ; optional, unused in netipfw.inf inf, used in netipfw_m.inf 11 | [ControlFlags] 12 | ExcludeFromSelect = unipi_ipfwmp 13 | 14 | ; destinationdirs section, optional 15 | [DestinationDirs] 16 | DefaultDestDir=12 17 | ; No files to copy 18 | 19 | ; manufacturer section 20 | [Manufacturer] 21 | %Unipi% = UNIPI,NTx86 22 | 23 | ; models section 24 | [UNIPI] ; Win2k 25 | %Desc% = IpfwMP.ndi, unipi_ipfwmp 26 | [UNIPI.NTx86] ;For WinXP and later 27 | %Desc% = IpfwMP.ndi, unipi_ipfwmp 28 | 29 | ; ddinstall section 30 | [IpfwMP.ndi] 31 | AddReg = IpfwMP.ndi.AddReg 32 | Characteristics = 0x29 ;NCF_NOT_USER_REMOVABLE | NCF_VIRTUAL | NCF_HIDDEN 33 | 34 | ; ddinstall->addreg points here 35 | [IpfwMP.ndi.AddReg] 36 | HKR, Ndi, Service, 0, IpfwMP 37 | 38 | ;ddinstall.services section 39 | [IpfwMP.ndi.Services] 40 | AddService = IpfwMP,0x2, IpfwMP.AddService 41 | 42 | [IpfwMP.AddService] 43 | ServiceType = 1 ;SERVICE_KERNEL_DRIVER 44 | StartType = 3 ;SERVICE_DEMAND_START 45 | ErrorControl = 1 ;SERVICE_ERROR_NORMAL 46 | ServiceBinary = %12%\ipfw.sys 47 | AddReg = IpfwMP.AddService.AddReg 48 | 49 | [IpfwMP.AddService.AddReg] 50 | ; None 51 | 52 | [Strings] 53 | Unipi = "Unipi" 54 | Desc = "Ipfw Miniport" 55 | -------------------------------------------------------------------------------- /third_party/jsmin/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Dave St.Germain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | 24 | -------------------------------------------------------------------------------- /third_party/jsmin/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt 2 | -------------------------------------------------------------------------------- /third_party/jsmin/README.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | jsmin 3 | ===== 4 | 5 | JavaScript minifier. 6 | 7 | Usage 8 | ===== 9 | 10 | .. code:: python 11 | 12 | from jsmin import jsmin 13 | with open('myfile.js') as js_file: 14 | minified = jsmin(js_file.read()) 15 | 16 | You can run it as a commandline tool also:: 17 | 18 | python -m jsmin myfile.js 19 | 20 | NB: ``jsmin`` makes no attempt to be compatible with 21 | `ECMAScript 6 / ES.next / Harmony `_. 22 | The current maintainer does not intend to add ES6-compatibility. If you would 23 | like to take over maintenance and update ``jsmin`` for ES6, please contact 24 | `Tikitu de Jager `_. Pull requests are also 25 | welcome, of course, but my time to review them is somewhat limited these days. 26 | 27 | If you're using ``jsmin`` on ES6 code, though, you might find the ``quote_chars`` 28 | parameter useful: 29 | 30 | .. code:: python 31 | 32 | from jsmin import jsmin 33 | with open('myfile.js') as js_file: 34 | minified = jsmin(js_file.read(), quote_chars="'\"`") 35 | 36 | 37 | Where to get it 38 | =============== 39 | 40 | * install the package `from pypi `_ 41 | * get the latest release `from latest-release on github `_ 42 | * get the development version `from master on github `_ 43 | 44 | Contributing 45 | ============ 46 | 47 | `Issues `_ and `Pull requests `_ 48 | will be gratefully received on Github. The project used to be hosted 49 | `on bitbucket `_ and old issues can still be 50 | found there. 51 | 52 | If possible, please make separate pull requests for tests and for code: tests will be added to the `latest-release` branch while code will go to `master`. 53 | 54 | Unless you request otherwise, your Github identity will be added to the contributor's list below; if you prefer a 55 | different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let 56 | the maintainer know somehow.) 57 | 58 | Build/test status 59 | ================= 60 | 61 | Both branches are tested with Travis: https://travis-ci.org/tikitu/jsmin 62 | 63 | The `latest-release` branch (the version on PyPI plus any new tests) is tested against CPython 2.6, 2.7, 3.2, and 3.3. 64 | Currently: 65 | 66 | .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=latest-release 67 | 68 | If that branch is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet 69 | released. 70 | 71 | The `master` branch (development version, might be ahead of latest released version) is tested against CPython 2.6, 2.7, 3.2, and 72 | 3.3. Currently: 73 | 74 | .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master 75 | 76 | If `master` is failing don't use it, but as long as `latest-release` is passing the pypi release should be ok. 77 | 78 | Contributors (chronological commit order) 79 | ========================================= 80 | 81 | * `Dave St.Germain `_ (original author) 82 | * `Hans weltar `_ 83 | * `Tikitu de Jager `_ (current maintainer) 84 | * https://bitbucket.org/rennat 85 | * `Nick Alexander `_ 86 | * `Gennady Kovshenin `_ 87 | * `Matt Molyneaux `_ 88 | -------------------------------------------------------------------------------- /third_party/jsmin/README.web-page-replay: -------------------------------------------------------------------------------- 1 | Name: JavaScript minifier 2 | Short Name: jsmin 3 | URL: https://pypi.python.org/pypi/jsmin 4 | Version: 2.2.1 5 | License: MIT 6 | License File: LICENSE.txt 7 | 8 | Description: 9 | Used by Web Page Replay's script_injector module to minify injected JS scripts. 10 | 11 | Local Modifications: 12 | Remove jsmin/__main__.py & jsmin/test.py since they are not needed and contain 13 | no license header (https://github.com/tikitu/jsmin/issues/17). 14 | -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright 2012 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | """Miscellaneous utility functions.""" 18 | 19 | import inspect 20 | import logging 21 | import time 22 | 23 | try: 24 | # pkg_resources (part of setuptools) is needed when WPR is 25 | # distributed as a package. (Resources may need to be extracted from 26 | # the package.) 27 | 28 | import pkg_resources 29 | 30 | def resource_exists(resource_name): 31 | return pkg_resources.resource_exists(__name__, resource_name) 32 | 33 | def resource_string(resource_name): 34 | return pkg_resources.resource_string(__name__, resource_name) 35 | 36 | except ImportError: 37 | # Import of pkg_resources failed, so fall back to getting resources 38 | # from the file system. 39 | 40 | import os 41 | 42 | def _resource_path(resource_name): 43 | _replay_dir = os.path.dirname(os.path.abspath(__file__)) 44 | return os.path.join(_replay_dir, resource_name) 45 | 46 | def resource_exists(resource_name): 47 | return os.path.exists(_resource_path(resource_name)) 48 | 49 | def resource_string(resource_name): 50 | return open(_resource_path(resource_name)).read() 51 | 52 | 53 | class TimeoutException(Exception): 54 | pass 55 | 56 | 57 | def WaitFor(condition, timeout): 58 | """Waits for up to |timeout| secs for the function |condition| to return True. 59 | 60 | Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s. 61 | 62 | Returns: 63 | Result of |condition| function (if present). 64 | """ 65 | min_poll_interval = 0.1 66 | max_poll_interval = 5 67 | output_interval = 300 68 | 69 | def GetConditionString(): 70 | if condition.__name__ == '': 71 | try: 72 | return inspect.getsource(condition).strip() 73 | except IOError: 74 | pass 75 | return condition.__name__ 76 | 77 | start_time = time.time() 78 | last_output_time = start_time 79 | while True: 80 | res = condition() 81 | if res: 82 | return res 83 | now = time.time() 84 | elapsed_time = now - start_time 85 | last_output_elapsed_time = now - last_output_time 86 | if elapsed_time > timeout: 87 | raise TimeoutException('Timed out while waiting %ds for %s.' % 88 | (timeout, GetConditionString())) 89 | if last_output_elapsed_time > output_interval: 90 | logging.info('Continuing to wait %ds for %s. Elapsed: %ds.', 91 | timeout, GetConditionString(), elapsed_time) 92 | last_output_time = time.time() 93 | poll_interval = min(max(elapsed_time / 10., min_poll_interval), 94 | max_poll_interval) 95 | time.sleep(poll_interval) 96 | -------------------------------------------------------------------------------- /wpr_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALLOoY1ENN78dMvO 3 | 33tSElddaaPFV4ooXJKbCqWsEurkKJjtoHxnri54rgNOLSU4O8aQytWE9zq6Ei/c 4 | qK7dl6UqZiZtwk4HVrBL786cVKlgpPkhcnG+EMdDxy/PyMD38jNtTNMJLiwbxiZq 5 | Mo3vjZ/4+1XLdNisAWTDLaWeXxmbAgMBAAECgYAadwLqScIZjvwqfkANnKQiUi0k 6 | lDzUsgyhllkJFGLoaUSo/eLXBvF851e6HYQJEj2msh+TYs7E3m16sAo3d4zOIdnz 7 | VwOF0SVuUveqJz6K1/k6nPxck+dPj8Mi+gBm3Fd0+0wcozjWaxhx3f462HCUb6b+ 8 | ZpJRBsbyvzu6rn7iQQJBAOlWhtfL8r9+Kl0vxRD1XukaJwlxPv24JhfKOU4z8WlJ 9 | WX7Wr8ws+xKS+CtfFnjkf/iFJPpTb8jxpQyWMJzYZIkCQQDELE5hGnBFVQArMAOp 10 | VbwYordTrVY3AagO4tDJ6T3a7GEXE28ol16/i02+4FLd65vubL21IuX0exH/eRvZ 11 | Q4wDAkEAub/qyiEOFkjOWq5rd0uNiY0LJGYlWf7dPDT8l3ecJ09/0gv/mE76c9fR 12 | fV1N22EzSlhbjncbVuCenj11Z3aP2QJAILtfzJXzu63GHG6jfcKfYuDrg9u9Mepl 13 | 1y4DNl1jg77DKG2Gs5gmKAGfVETrrrmcR/j+4lVTVyqdwym6+tJpbwJBAN3vixxc 14 | 5N9pUMDfFnHrx/x9QPd0JgSAT21KSIB+PndlbD7QO6nwFhQNNcTYt2D4VWPVo1vg 15 | lOraHyFakb7NqEA= 16 | -----END PRIVATE KEY----- 17 | -----BEGIN CERTIFICATE----- 18 | MIICWDCCAcGgAwIBAgIJAIt1sARz1phuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 19 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 20 | aWRnaXRzIFB0eSBMdGQwHhcNMTIxMDIzMjA1NzA0WhcNMjIxMDIxMjA1NzA0WjBF 21 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 22 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB 23 | gQCyzqGNRDTe/HTLzt97UhJXXWmjxVeKKFySmwqlrBLq5CiY7aB8Z64ueK4DTi0l 24 | ODvGkMrVhPc6uhIv3Kiu3ZelKmYmbcJOB1awS+/OnFSpYKT5IXJxvhDHQ8cvz8jA 25 | 9/IzbUzTCS4sG8YmajKN742f+PtVy3TYrAFkwy2lnl8ZmwIDAQABo1AwTjAdBgNV 26 | HQ4EFgQUyihF4Nbabk9aBDOOxMVDLRLiqMEwHwYDVR0jBBgwFoAUyihF4Nbabk9a 27 | BDOOxMVDLRLiqMEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCIrYif 28 | q4YQ7A8zy8PB1wKOyMy50r7IokO8hplbjRwVCQwbLnRM74LPp84caEdwaCJvAaP9 29 | QWjVz6p3K2sK9iHaidQZ/9xqJPoZrYttQCcQUweaASp04Y9WwTA4EPeDZLgp4PgU 30 | SV/mvKRGimmce6LMxFlPiZio/IDiUNXVJ7j/sg== 31 | -----END CERTIFICATE----- 32 | --------------------------------------------------------------------------------