├── intercom
├── gdata
│ ├── sites
│ │ └── __init__.py
│ ├── apps
│ │ ├── groups
│ │ │ └── __init__.py
│ │ ├── audit
│ │ │ └── __init__.py
│ │ ├── organization
│ │ │ └── __init__.py
│ │ ├── emailsettings
│ │ │ └── __init__.py
│ │ ├── adminsettings
│ │ │ └── __init__.py
│ │ └── migration
│ │ │ └── service.py
│ ├── marketplace
│ │ ├── __init__.py
│ │ └── data.py
│ ├── spreadsheets
│ │ └── __init__.py
│ ├── projecthosting
│ │ ├── __init__.py
│ │ └── data.py
│ ├── calendar_resource
│ │ └── __init__.py
│ ├── Crypto
│ │ ├── Hash
│ │ │ ├── MD2.pyd
│ │ │ ├── MD4.pyd
│ │ │ ├── RIPEMD.pyd
│ │ │ ├── SHA256.pyd
│ │ │ ├── SHA.py
│ │ │ ├── MD5.py
│ │ │ ├── __init__.py
│ │ │ └── HMAC.py
│ │ ├── Cipher
│ │ │ ├── AES.pyd
│ │ │ ├── ARC2.pyd
│ │ │ ├── ARC4.pyd
│ │ │ ├── CAST.pyd
│ │ │ ├── DES.pyd
│ │ │ ├── DES3.pyd
│ │ │ ├── IDEA.pyd
│ │ │ ├── RC5.pyd
│ │ │ ├── XOR.pyd
│ │ │ ├── Blowfish.pyd
│ │ │ └── __init__.py
│ │ ├── Util
│ │ │ └── __init__.py
│ │ ├── Protocol
│ │ │ └── __init__.py
│ │ ├── PublicKey
│ │ │ ├── __init__.py
│ │ │ └── ElGamal.py
│ │ ├── test.py
│ │ └── __init__.py
│ ├── tlslite
│ │ ├── utils
│ │ │ ├── RC4.py
│ │ │ ├── PyCrypto_RC4.py
│ │ │ ├── PyCrypto_AES.py
│ │ │ ├── OpenSSL_RC4.py
│ │ │ ├── PyCrypto_TripleDES.py
│ │ │ ├── TripleDES.py
│ │ │ ├── __init__.py
│ │ │ ├── Cryptlib_RC4.py
│ │ │ ├── AES.py
│ │ │ ├── ASN1Parser.py
│ │ │ ├── Python_RC4.py
│ │ │ ├── win32prng.c
│ │ │ ├── Cryptlib_AES.py
│ │ │ ├── Cryptlib_TripleDES.py
│ │ │ ├── OpenSSL_TripleDES.py
│ │ │ ├── OpenSSL_AES.py
│ │ │ ├── PyCrypto_RSAKey.py
│ │ │ ├── Python_AES.py
│ │ │ ├── dateFuncs.py
│ │ │ ├── codec.py
│ │ │ ├── cipherfactory.py
│ │ │ ├── hmac.py
│ │ │ └── compat.py
│ │ ├── integration
│ │ │ ├── __init__.py
│ │ │ ├── IntegrationHelper.py
│ │ │ ├── TLSSocketServerMixIn.py
│ │ │ ├── SMTP_TLS.py
│ │ │ └── TLSAsyncDispatcherMixIn.py
│ │ ├── __init__.py
│ │ ├── SharedKeyDB.py
│ │ ├── api.py
│ │ ├── VerifierDB.py
│ │ ├── SessionCache.py
│ │ ├── BaseDB.py
│ │ ├── X509.py
│ │ └── Session.py
│ ├── acl
│ │ ├── __init__.py
│ │ └── data.py
│ ├── dublincore
│ │ ├── __init__.py
│ │ └── data.py
│ ├── notebook
│ │ ├── __init__.py
│ │ └── data.py
│ ├── opensearch
│ │ ├── __init__.py
│ │ └── data.py
│ ├── contentforshopping
│ │ └── __init__.py
│ ├── oauth
│ │ ├── CHANGES.txt
│ │ └── rsa.py
│ ├── alt
│ │ ├── __init__.py
│ │ └── app_engine.py
│ ├── apps_property.py
│ ├── geo
│ │ └── data.py
│ ├── books
│ │ └── data.py
│ ├── media
│ │ └── data.py
│ ├── finance
│ │ └── data.py
│ ├── codesearch
│ │ ├── service.py
│ │ └── __init__.py
│ └── blogger
│ │ └── data.py
├── twilio
│ ├── contrib
│ │ ├── __init__.py
│ │ ├── jwt
│ │ │ └── __init__.py
│ │ └── httplib2
│ │ │ └── iri2uri.py
│ ├── __init__.py
│ ├── rest
│ │ └── __init__.py
│ └── util.py
├── static
│ ├── images
│ │ ├── logo.png
│ │ ├── noisy.png
│ │ └── padded.png
│ └── css
│ │ └── intercom.css
├── templates
│ └── twiml.html
├── settings.py
├── .gitignore
├── index.yaml
├── app.yaml
├── organization.py
├── atom
│ ├── auth.py
│ ├── token_store.py
│ ├── url.py
│ └── mock_http.py
├── README.md
└── main.py
├── README.md
└── LICENSE
/intercom/gdata/sites/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/groups/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intercom/twilio/contrib/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/audit/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/intercom/gdata/marketplace/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/intercom/gdata/spreadsheets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/organization/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/intercom/gdata/projecthosting/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/intercom/gdata/calendar_resource/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/intercom/static/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/static/images/logo.png
--------------------------------------------------------------------------------
/intercom/static/images/noisy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/static/images/noisy.png
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/MD2.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Hash/MD2.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/MD4.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Hash/MD4.pyd
--------------------------------------------------------------------------------
/intercom/static/images/padded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/static/images/padded.png
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/AES.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/AES.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/ARC2.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/ARC2.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/ARC4.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/ARC4.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/CAST.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/CAST.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/DES.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/DES.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/DES3.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/DES3.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/IDEA.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/IDEA.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/RC5.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/RC5.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/XOR.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/XOR.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/RIPEMD.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Hash/RIPEMD.pyd
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/SHA256.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Hash/SHA256.pyd
--------------------------------------------------------------------------------
/intercom/templates/twiml.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{client}}
4 |
5 |
6 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/Blowfish.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/howtos/HEAD/intercom/gdata/Crypto/Cipher/Blowfish.pyd
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Example Twilio Applications
2 |
3 | To help get you up and running on with Twilio, we provide sample applications for common use cases.
4 |
5 | ## Twilio Client
6 |
7 | * [Twilio Intercom](https://github.com/twilio/howtos/tree/master/intercom)
8 |
9 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/SHA.py:
--------------------------------------------------------------------------------
1 |
2 | # Just use the SHA module from the Python standard library
3 |
4 | __revision__ = "$Id: SHA.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $"
5 |
6 | from sha import *
7 | import sha
8 | if hasattr(sha, 'digestsize'):
9 | digest_size = digestsize
10 | del digestsize
11 | del sha
12 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/MD5.py:
--------------------------------------------------------------------------------
1 |
2 | # Just use the MD5 module from the Python standard library
3 |
4 | __revision__ = "$Id: MD5.py,v 1.4 2002/07/11 14:31:19 akuchling Exp $"
5 |
6 | from md5 import *
7 |
8 | import md5
9 | if hasattr(md5, 'digestsize'):
10 | digest_size = digestsize
11 | del digestsize
12 | del md5
13 |
14 |
--------------------------------------------------------------------------------
/intercom/settings.py:
--------------------------------------------------------------------------------
1 | AUTH_TOKEN = "" # Your Twilio Auth Token
2 | ACCOUNT_SID = "" # Your Twilio Account Sid
3 | APP_SID = "" # Your TwiML Application Sid
4 |
5 | CONSUMER_KEY = "" # Consumer Token key from Google Apps
6 | CONSUMER_SECRET = '' # Consumer Secret key from Google Apps
7 | REQUESTOR = "" # Your Google Apps username
8 |
--------------------------------------------------------------------------------
/intercom/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[co]
2 |
3 | # Packages
4 | *.egg
5 | *.egg-info
6 | dist
7 | build
8 | eggs
9 | parts
10 | bin
11 | var
12 | sdist
13 | develop-eggs
14 | .installed.cfg
15 |
16 | # Installer logs
17 | pip-log.txt
18 |
19 | # Unit test / coverage reports
20 | .coverage
21 | .tox
22 |
23 | #Translations
24 | *.mo
25 |
26 | #Mr Developer
27 | .mr.developer.cfg
--------------------------------------------------------------------------------
/intercom/twilio/__init__.py:
--------------------------------------------------------------------------------
1 | __version_info__ = ('3', '2', '3')
2 | __version__ = '.'.join(__version_info__)
3 |
4 |
5 | class TwilioException(Exception):
6 | pass
7 |
8 |
9 | class TwilioRestException(TwilioException):
10 |
11 | def __init__(self, status, uri, msg=""):
12 | self.uri = uri
13 | self.status = status
14 | self.msg = msg
15 |
16 | def __str__(self):
17 | return "HTTP ERROR %s: %s \n %s" % (self.status, self.msg, self.uri)
18 |
--------------------------------------------------------------------------------
/intercom/index.yaml:
--------------------------------------------------------------------------------
1 | indexes:
2 |
3 | # AUTOGENERATED
4 |
5 | # This index.yaml is automatically updated whenever the dev_appserver
6 | # detects that a new type of query is run. If you want to manage the
7 | # index.yaml file manually, remove the above marker line (the line
8 | # saying "# AUTOGENERATED"). If you want to manage some indexes
9 | # manually, move them above the marker line. The index.yaml file is
10 | # automatically uploaded to the admin console when you next deploy
11 | # your application using appcfg.py.
12 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/RC4.py:
--------------------------------------------------------------------------------
1 | """Abstract class for RC4."""
2 |
3 | from compat import * #For False
4 |
5 | class RC4:
6 | def __init__(self, keyBytes, implementation):
7 | if len(keyBytes) < 16 or len(keyBytes) > 256:
8 | raise ValueError()
9 | self.isBlockCipher = False
10 | self.name = "rc4"
11 | self.implementation = implementation
12 |
13 | def encrypt(self, plaintext):
14 | raise NotImplementedError()
15 |
16 | def decrypt(self, ciphertext):
17 | raise NotImplementedError()
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/integration/__init__.py:
--------------------------------------------------------------------------------
1 | """Classes for integrating TLS Lite with other packages."""
2 |
3 | __all__ = ["AsyncStateMachine",
4 | "HTTPTLSConnection",
5 | "POP3_TLS",
6 | "IMAP4_TLS",
7 | "SMTP_TLS",
8 | "XMLRPCTransport",
9 | "TLSSocketServerMixIn",
10 | "TLSAsyncDispatcherMixIn",
11 | "TLSTwistedProtocolWrapper"]
12 |
13 | try:
14 | import twisted
15 | del twisted
16 | except ImportError:
17 | del __all__[__all__.index("TLSTwistedProtocolWrapper")]
18 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Util/__init__.py:
--------------------------------------------------------------------------------
1 | """Miscellaneous modules
2 |
3 | Contains useful modules that don't belong into any of the
4 | other Crypto.* subpackages.
5 |
6 | Crypto.Util.number Number-theoretic functions (primality testing, etc.)
7 | Crypto.Util.randpool Random number generation
8 | Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable
9 | strings of words.
10 |
11 | """
12 |
13 | __all__ = ['randpool', 'RFC1751', 'number']
14 |
15 | __revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:26:00 akuchling Exp $"
16 |
17 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/PyCrypto_RC4.py:
--------------------------------------------------------------------------------
1 | """PyCrypto RC4 implementation."""
2 |
3 | from cryptomath import *
4 | from RC4 import *
5 |
6 | if pycryptoLoaded:
7 | import Crypto.Cipher.ARC4
8 |
9 | def new(key):
10 | return PyCrypto_RC4(key)
11 |
12 | class PyCrypto_RC4(RC4):
13 |
14 | def __init__(self, key):
15 | RC4.__init__(self, key, "pycrypto")
16 | self.context = Crypto.Cipher.ARC4.new(key)
17 |
18 | def encrypt(self, plaintext):
19 | return self.context.encrypt(plaintext)
20 |
21 | def decrypt(self, ciphertext):
22 | return self.context.decrypt(ciphertext)
--------------------------------------------------------------------------------
/intercom/gdata/acl/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
--------------------------------------------------------------------------------
/intercom/gdata/dublincore/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
--------------------------------------------------------------------------------
/intercom/gdata/notebook/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
--------------------------------------------------------------------------------
/intercom/gdata/opensearch/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/emailsettings/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2008 Google
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 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/adminsettings/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2008 Google
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 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/PyCrypto_AES.py:
--------------------------------------------------------------------------------
1 | """PyCrypto AES implementation."""
2 |
3 | from cryptomath import *
4 | from AES import *
5 |
6 | if pycryptoLoaded:
7 | import Crypto.Cipher.AES
8 |
9 | def new(key, mode, IV):
10 | return PyCrypto_AES(key, mode, IV)
11 |
12 | class PyCrypto_AES(AES):
13 |
14 | def __init__(self, key, mode, IV):
15 | AES.__init__(self, key, mode, IV, "pycrypto")
16 | self.context = Crypto.Cipher.AES.new(key, mode, IV)
17 |
18 | def encrypt(self, plaintext):
19 | return self.context.encrypt(plaintext)
20 |
21 | def decrypt(self, ciphertext):
22 | return self.context.decrypt(ciphertext)
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/OpenSSL_RC4.py:
--------------------------------------------------------------------------------
1 | """OpenSSL/M2Crypto RC4 implementation."""
2 |
3 | from cryptomath import *
4 | from RC4 import RC4
5 |
6 | if m2cryptoLoaded:
7 |
8 | def new(key):
9 | return OpenSSL_RC4(key)
10 |
11 | class OpenSSL_RC4(RC4):
12 |
13 | def __init__(self, key):
14 | RC4.__init__(self, key, "openssl")
15 | self.rc4 = m2.rc4_new()
16 | m2.rc4_set_key(self.rc4, key)
17 |
18 | def __del__(self):
19 | m2.rc4_free(self.rc4)
20 |
21 | def encrypt(self, plaintext):
22 | return m2.rc4_update(self.rc4, plaintext)
23 |
24 | def decrypt(self, ciphertext):
25 | return self.encrypt(ciphertext)
26 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/PyCrypto_TripleDES.py:
--------------------------------------------------------------------------------
1 | """PyCrypto 3DES implementation."""
2 |
3 | from cryptomath import *
4 | from TripleDES import *
5 |
6 | if pycryptoLoaded:
7 | import Crypto.Cipher.DES3
8 |
9 | def new(key, mode, IV):
10 | return PyCrypto_TripleDES(key, mode, IV)
11 |
12 | class PyCrypto_TripleDES(TripleDES):
13 |
14 | def __init__(self, key, mode, IV):
15 | TripleDES.__init__(self, key, mode, IV, "pycrypto")
16 | self.context = Crypto.Cipher.DES3.new(key, mode, IV)
17 |
18 | def encrypt(self, plaintext):
19 | return self.context.encrypt(plaintext)
20 |
21 | def decrypt(self, ciphertext):
22 | return self.context.decrypt(ciphertext)
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Protocol/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | """Cryptographic protocols
3 |
4 | Implements various cryptographic protocols. (Don't expect to find
5 | network protocols here.)
6 |
7 | Crypto.Protocol.AllOrNothing Transforms a message into a set of message
8 | blocks, such that the blocks can be
9 | recombined to get the message back.
10 |
11 | Crypto.Protocol.Chaffing Takes a set of authenticated message blocks
12 | (the wheat) and adds a number of
13 | randomly generated blocks (the chaff).
14 | """
15 |
16 | __all__ = ['AllOrNothing', 'Chaffing']
17 | __revision__ = "$Id: __init__.py,v 1.4 2003/02/28 15:23:21 akuchling Exp $"
18 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/PublicKey/__init__.py:
--------------------------------------------------------------------------------
1 | """Public-key encryption and signature algorithms.
2 |
3 | Public-key encryption uses two different keys, one for encryption and
4 | one for decryption. The encryption key can be made public, and the
5 | decryption key is kept private. Many public-key algorithms can also
6 | be used to sign messages, and some can *only* be used for signatures.
7 |
8 | Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only)
9 | Crypto.PublicKey.ElGamal (Signing and encryption)
10 | Crypto.PublicKey.RSA (Signing, encryption, and blinding)
11 | Crypto.PublicKey.qNEW (Signature only)
12 |
13 | """
14 |
15 | __all__ = ['RSA', 'DSA', 'ElGamal', 'qNEW']
16 | __revision__ = "$Id: __init__.py,v 1.4 2003/04/03 20:27:13 akuchling Exp $"
17 |
18 |
--------------------------------------------------------------------------------
/intercom/app.yaml:
--------------------------------------------------------------------------------
1 | application: twilio-intercom
2 | version: 1
3 | runtime: python
4 | api_version: 1
5 |
6 | builtins:
7 | - remote_api: on
8 |
9 | handlers:
10 | - url: /console/.*
11 | script: $PYTHON_LIB/google/appengine/ext/admin
12 | login: admin
13 | - url: /js
14 | static_dir: static/js
15 | - url: /images
16 | static_dir: static/images
17 | - url: /css
18 | static_dir: static/css
19 | - url: /call
20 | script: main.py
21 | - url: .*
22 | script: main.py
23 | login: required
24 |
25 | admin_console:
26 | pages:
27 | - name: Memcache
28 | url: /console/memcache
29 |
30 | skip_files: |
31 | ^(.*/)?(
32 | (#.*#)|
33 | (.*~)|
34 | (.*\.py[co])|
35 | (.*/RCS/.*)|
36 | (\..*)|
37 | (dev/.*)|
38 | (tests/.*)|
39 | (docs/.*)|
40 | (.*\.markdown)|
41 | (license\.txt)|
42 | (setup.py)
43 | )$
44 |
--------------------------------------------------------------------------------
/intercom/gdata/contentforshopping/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2010-2011 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 |
18 | """Support for the Content API for Shopping
19 |
20 | See: http://code.google.com/apis/shopping/content/index.html
21 | """
22 |
--------------------------------------------------------------------------------
/intercom/gdata/oauth/CHANGES.txt:
--------------------------------------------------------------------------------
1 | 1. Moved oauth.py to __init__.py
2 |
3 | 2. Refactored __init__.py for compatibility with python 2.2 (Issue 59)
4 |
5 | 3. Refactored rsa.py for compatibility with python 2.2 (Issue 59)
6 |
7 | 4. Refactored OAuthRequest.from_token_and_callback since the callback url was
8 | getting double url-encoding the callback url in place of single. (Issue 43)
9 |
10 | 5. Added build_signature_base_string method to rsa.py since it used the
11 | implementation of this method from oauth.OAuthSignatureMethod_HMAC_SHA1 which
12 | was incorrect since it enforced the presence of a consumer secret and a token
13 | secret. Also, changed its super class from oauth.OAuthSignatureMethod_HMAC_SHA1
14 | to oauth.OAuthSignatureMethod (Issue 64)
15 |
16 | 6. Refactored .to_header method since it returned non-oauth params
17 | as well which was incorrect. (Issue 31)
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/TripleDES.py:
--------------------------------------------------------------------------------
1 | """Abstract class for 3DES."""
2 |
3 | from compat import * #For True
4 |
5 | class TripleDES:
6 | def __init__(self, key, mode, IV, implementation):
7 | if len(key) != 24:
8 | raise ValueError()
9 | if mode != 2:
10 | raise ValueError()
11 | if len(IV) != 8:
12 | raise ValueError()
13 | self.isBlockCipher = True
14 | self.block_size = 8
15 | self.implementation = implementation
16 | self.name = "3des"
17 |
18 | #CBC-Mode encryption, returns ciphertext
19 | #WARNING: *MAY* modify the input as well
20 | def encrypt(self, plaintext):
21 | assert(len(plaintext) % 8 == 0)
22 |
23 | #CBC-Mode decryption, returns plaintext
24 | #WARNING: *MAY* modify the input as well
25 | def decrypt(self, ciphertext):
26 | assert(len(ciphertext) % 8 == 0)
27 |
--------------------------------------------------------------------------------
/intercom/gdata/alt/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 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 | """This package's modules adapt the gdata library to run in other environments
17 |
18 | The first example is the appengine module which contains functions and
19 | classes which modify a GDataService object to run on Google App Engine.
20 | """
21 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/__init__.py:
--------------------------------------------------------------------------------
1 | """Hashing algorithms
2 |
3 | Hash functions take arbitrary strings as input, and produce an output
4 | of fixed size that is dependent on the input; it should never be
5 | possible to derive the input data given only the hash function's
6 | output. Hash functions can be used simply as a checksum, or, in
7 | association with a public-key algorithm, can be used to implement
8 | digital signatures.
9 |
10 | The hashing modules here all support the interface described in PEP
11 | 247, "API for Cryptographic Hash Functions".
12 |
13 | Submodules:
14 | Crypto.Hash.HMAC RFC 2104: Keyed-Hashing for Message Authentication
15 | Crypto.Hash.MD2
16 | Crypto.Hash.MD4
17 | Crypto.Hash.MD5
18 | Crypto.Hash.RIPEMD
19 | Crypto.Hash.SHA
20 | """
21 |
22 | __all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'SHA', 'SHA256']
23 | __revision__ = "$Id: __init__.py,v 1.6 2003/12/19 14:24:25 akuchling Exp $"
24 |
25 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/__init__.py:
--------------------------------------------------------------------------------
1 | """Toolkit for crypto and other stuff."""
2 |
3 | __all__ = ["AES",
4 | "ASN1Parser",
5 | "cipherfactory",
6 | "codec",
7 | "Cryptlib_AES",
8 | "Cryptlib_RC4",
9 | "Cryptlib_TripleDES",
10 | "cryptomath: cryptomath module",
11 | "dateFuncs",
12 | "hmac",
13 | "JCE_RSAKey",
14 | "compat",
15 | "keyfactory",
16 | "OpenSSL_AES",
17 | "OpenSSL_RC4",
18 | "OpenSSL_RSAKey",
19 | "OpenSSL_TripleDES",
20 | "PyCrypto_AES",
21 | "PyCrypto_RC4",
22 | "PyCrypto_RSAKey",
23 | "PyCrypto_TripleDES",
24 | "Python_AES",
25 | "Python_RC4",
26 | "Python_RSAKey",
27 | "RC4",
28 | "rijndael",
29 | "RSAKey",
30 | "TripleDES",
31 | "xmltools"]
32 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/test.py:
--------------------------------------------------------------------------------
1 | #
2 | # Test script for the Python Cryptography Toolkit.
3 | #
4 |
5 | __revision__ = "$Id: test.py,v 1.7 2002/07/11 14:31:19 akuchling Exp $"
6 |
7 | import os, sys
8 |
9 |
10 | # Add the build directory to the front of sys.path
11 | from distutils.util import get_platform
12 | s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
13 | s = os.path.join(os.getcwd(), s)
14 | sys.path.insert(0, s)
15 | s = os.path.join(os.getcwd(), 'test')
16 | sys.path.insert(0, s)
17 |
18 | from Crypto.Util import test
19 |
20 | args = sys.argv[1:]
21 | quiet = "--quiet" in args
22 | if quiet: args.remove('--quiet')
23 |
24 | if not quiet:
25 | print '\nStream Ciphers:'
26 | print '==============='
27 |
28 | if args: test.TestStreamModules(args, verbose= not quiet)
29 | else: test.TestStreamModules(verbose= not quiet)
30 |
31 | if not quiet:
32 | print '\nBlock Ciphers:'
33 | print '=============='
34 |
35 | if args: test.TestBlockModules(args, verbose= not quiet)
36 | else: test.TestBlockModules(verbose= not quiet)
37 |
38 |
39 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | """Python Cryptography Toolkit
3 |
4 | A collection of cryptographic modules implementing various algorithms
5 | and protocols.
6 |
7 | Subpackages:
8 | Crypto.Cipher Secret-key encryption algorithms (AES, DES, ARC4)
9 | Crypto.Hash Hashing algorithms (MD5, SHA, HMAC)
10 | Crypto.Protocol Cryptographic protocols (Chaffing, all-or-nothing
11 | transform). This package does not contain any
12 | network protocols.
13 | Crypto.PublicKey Public-key encryption and signature algorithms
14 | (RSA, DSA)
15 | Crypto.Util Various useful modules and functions (long-to-string
16 | conversion, random number generation, number
17 | theoretic functions)
18 | """
19 |
20 | __all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util']
21 |
22 | __version__ = '2.0.1'
23 | __revision__ = "$Id: __init__.py,v 1.12 2005/06/14 01:20:22 akuchling Exp $"
24 |
25 |
26 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/Cryptlib_RC4.py:
--------------------------------------------------------------------------------
1 | """Cryptlib RC4 implementation."""
2 |
3 | from cryptomath import *
4 | from RC4 import RC4
5 |
6 | if cryptlibpyLoaded:
7 |
8 | def new(key):
9 | return Cryptlib_RC4(key)
10 |
11 | class Cryptlib_RC4(RC4):
12 |
13 | def __init__(self, key):
14 | RC4.__init__(self, key, "cryptlib")
15 | self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_RC4)
16 | cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key))
17 | cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key)
18 |
19 | def __del__(self):
20 | cryptlib_py.cryptDestroyContext(self.context)
21 |
22 | def encrypt(self, plaintext):
23 | bytes = stringToBytes(plaintext)
24 | cryptlib_py.cryptEncrypt(self.context, bytes)
25 | return bytesToString(bytes)
26 |
27 | def decrypt(self, ciphertext):
28 | return self.encrypt(ciphertext)
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/AES.py:
--------------------------------------------------------------------------------
1 | """Abstract class for AES."""
2 |
3 | class AES:
4 | def __init__(self, key, mode, IV, implementation):
5 | if len(key) not in (16, 24, 32):
6 | raise AssertionError()
7 | if mode != 2:
8 | raise AssertionError()
9 | if len(IV) != 16:
10 | raise AssertionError()
11 | self.isBlockCipher = True
12 | self.block_size = 16
13 | self.implementation = implementation
14 | if len(key)==16:
15 | self.name = "aes128"
16 | elif len(key)==24:
17 | self.name = "aes192"
18 | elif len(key)==32:
19 | self.name = "aes256"
20 | else:
21 | raise AssertionError()
22 |
23 | #CBC-Mode encryption, returns ciphertext
24 | #WARNING: *MAY* modify the input as well
25 | def encrypt(self, plaintext):
26 | assert(len(plaintext) % 16 == 0)
27 |
28 | #CBC-Mode decryption, returns plaintext
29 | #WARNING: *MAY* modify the input as well
30 | def decrypt(self, ciphertext):
31 | assert(len(ciphertext) % 16 == 0)
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/ASN1Parser.py:
--------------------------------------------------------------------------------
1 | """Class for parsing ASN.1"""
2 | from compat import *
3 | from codec import *
4 |
5 | #Takes a byte array which has a DER TLV field at its head
6 | class ASN1Parser:
7 | def __init__(self, bytes):
8 | p = Parser(bytes)
9 | p.get(1) #skip Type
10 |
11 | #Get Length
12 | self.length = self._getASN1Length(p)
13 |
14 | #Get Value
15 | self.value = p.getFixBytes(self.length)
16 |
17 | #Assuming this is a sequence...
18 | def getChild(self, which):
19 | p = Parser(self.value)
20 | for x in range(which+1):
21 | markIndex = p.index
22 | p.get(1) #skip Type
23 | length = self._getASN1Length(p)
24 | p.getFixBytes(length)
25 | return ASN1Parser(p.bytes[markIndex : p.index])
26 |
27 | #Decode the ASN.1 DER length field
28 | def _getASN1Length(self, p):
29 | firstLength = p.get(1)
30 | if firstLength<=127:
31 | return firstLength
32 | else:
33 | lengthLength = firstLength & 0x7F
34 | return p.get(lengthLength)
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 Twilio, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/intercom/organization.py:
--------------------------------------------------------------------------------
1 | import gdata
2 | import settings
3 | from gdata.alt.appengine import run_on_appengine
4 | from gdata.apps.service import AppsService
5 | from google.appengine.api import memcache
6 |
7 |
8 | SIG_METHOD = gdata.auth.OAuthSignatureMethod.HMAC_SHA1
9 |
10 |
11 | def users():
12 | results = memcache.get("roster")
13 |
14 | if results is not None:
15 | return results
16 |
17 | apps = AppsService(domain=settings.CONSUMER_KEY, source="intercom")
18 | apps.SetOAuthInputParameters(
19 | SIG_METHOD, settings.CONSUMER_KEY,
20 | consumer_secret=settings.CONSUMER_SECRET,
21 | two_legged_oauth=True, requestor_id=settings.REQUESTOR)
22 | feed = apps.GetGeneratorForAllUsers()
23 |
24 | results = []
25 |
26 | def get_person(person):
27 | return {
28 | "name": "%s %s" % (person.name.given_name,
29 | person.name.family_name),
30 | "id": person.login.user_name,
31 | }
32 |
33 | for entry in feed:
34 | for person in entry.entry:
35 | results.append(get_person(person))
36 |
37 | memcache.add("roster", results, 14400)
38 | return results
39 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/Python_RC4.py:
--------------------------------------------------------------------------------
1 | """Pure-Python RC4 implementation."""
2 |
3 | from RC4 import RC4
4 | from cryptomath import *
5 |
6 | def new(key):
7 | return Python_RC4(key)
8 |
9 | class Python_RC4(RC4):
10 | def __init__(self, key):
11 | RC4.__init__(self, key, "python")
12 | keyBytes = stringToBytes(key)
13 | S = [i for i in range(256)]
14 | j = 0
15 | for i in range(256):
16 | j = (j + S[i] + keyBytes[i % len(keyBytes)]) % 256
17 | S[i], S[j] = S[j], S[i]
18 |
19 | self.S = S
20 | self.i = 0
21 | self.j = 0
22 |
23 | def encrypt(self, plaintext):
24 | plaintextBytes = stringToBytes(plaintext)
25 | S = self.S
26 | i = self.i
27 | j = self.j
28 | for x in range(len(plaintextBytes)):
29 | i = (i + 1) % 256
30 | j = (j + S[i]) % 256
31 | S[i], S[j] = S[j], S[i]
32 | t = (S[i] + S[j]) % 256
33 | plaintextBytes[x] ^= S[t]
34 | self.i = i
35 | self.j = j
36 | return bytesToString(plaintextBytes)
37 |
38 | def decrypt(self, ciphertext):
39 | return self.encrypt(ciphertext)
40 |
--------------------------------------------------------------------------------
/intercom/gdata/apps_property.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright (C) 2010 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 |
18 | # This module is used for version 2 of the Google Data APIs.
19 |
20 |
21 | """Provides a base class to represent property elements in feeds.
22 |
23 | This module is used for version 2 of the Google Data APIs. The primary class
24 | in this module is AppsProperty.
25 | """
26 |
27 |
28 | __author__ = 'Vic Fryzel '
29 |
30 |
31 | import atom.core
32 | import gdata.apps
33 |
34 |
35 | class AppsProperty(atom.core.XmlElement):
36 | """Represents an element in a feed."""
37 | _qname = gdata.apps.APPS_TEMPLATE % 'property'
38 | name = 'name'
39 | value = 'value'
40 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Cipher/__init__.py:
--------------------------------------------------------------------------------
1 | """Secret-key encryption algorithms.
2 |
3 | Secret-key encryption algorithms transform plaintext in some way that
4 | is dependent on a key, producing ciphertext. This transformation can
5 | easily be reversed, if (and, hopefully, only if) one knows the key.
6 |
7 | The encryption modules here all support the interface described in PEP
8 | 272, "API for Block Encryption Algorithms".
9 |
10 | If you don't know which algorithm to choose, use AES because it's
11 | standard and has undergone a fair bit of examination.
12 |
13 | Crypto.Cipher.AES Advanced Encryption Standard
14 | Crypto.Cipher.ARC2 Alleged RC2
15 | Crypto.Cipher.ARC4 Alleged RC4
16 | Crypto.Cipher.Blowfish
17 | Crypto.Cipher.CAST
18 | Crypto.Cipher.DES The Data Encryption Standard. Very commonly used
19 | in the past, but today its 56-bit keys are too small.
20 | Crypto.Cipher.DES3 Triple DES.
21 | Crypto.Cipher.IDEA
22 | Crypto.Cipher.RC5
23 | Crypto.Cipher.XOR The simple XOR cipher.
24 | """
25 |
26 | __all__ = ['AES', 'ARC2', 'ARC4',
27 | 'Blowfish', 'CAST', 'DES', 'DES3', 'IDEA', 'RC5',
28 | 'XOR'
29 | ]
30 |
31 | __revision__ = "$Id: __init__.py,v 1.7 2003/02/28 15:28:35 akuchling Exp $"
32 |
33 |
34 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | TLS Lite is a free python library that implements SSL v3, TLS v1, and
3 | TLS v1.1. TLS Lite supports non-traditional authentication methods
4 | such as SRP, shared keys, and cryptoIDs, in addition to X.509
5 | certificates. TLS Lite is pure python, however it can access OpenSSL,
6 | cryptlib, pycrypto, and GMPY for faster crypto operations. TLS Lite
7 | integrates with httplib, xmlrpclib, poplib, imaplib, smtplib,
8 | SocketServer, asyncore, and Twisted.
9 |
10 | To use, do::
11 |
12 | from tlslite.api import *
13 |
14 | Then use the L{tlslite.TLSConnection.TLSConnection} class with a socket,
15 | or use one of the integration classes in L{tlslite.integration}.
16 |
17 | @version: 0.3.8
18 | """
19 | __version__ = "0.3.8"
20 |
21 | __all__ = ["api",
22 | "BaseDB",
23 | "Checker",
24 | "constants",
25 | "errors",
26 | "FileObject",
27 | "HandshakeSettings",
28 | "mathtls",
29 | "messages",
30 | "Session",
31 | "SessionCache",
32 | "SharedKeyDB",
33 | "TLSConnection",
34 | "TLSRecordLayer",
35 | "VerifierDB",
36 | "X509",
37 | "X509CertChain",
38 | "integration",
39 | "utils"]
40 |
--------------------------------------------------------------------------------
/intercom/atom/auth.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright (C) 2009 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 |
18 | # This module is used for version 2 of the Google Data APIs.
19 |
20 |
21 | __author__ = 'j.s@google.com (Jeff Scudder)'
22 |
23 |
24 | import base64
25 |
26 |
27 | class BasicAuth(object):
28 | """Sets the Authorization header as defined in RFC1945"""
29 |
30 | def __init__(self, user_id, password):
31 | self.basic_cookie = base64.encodestring(
32 | '%s:%s' % (user_id, password)).strip()
33 |
34 | def modify_request(self, http_request):
35 | http_request.headers['Authorization'] = 'Basic %s' % self.basic_cookie
36 |
37 | ModifyRequest = modify_request
38 |
39 |
40 | class NoAuth(object):
41 |
42 | def modify_request(self, http_request):
43 | pass
44 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/win32prng.c:
--------------------------------------------------------------------------------
1 |
2 | #include "Python.h"
3 | #define _WIN32_WINNT 0x0400 /* Needed for CryptoAPI on some systems */
4 | #include
5 |
6 |
7 | static PyObject* getRandomBytes(PyObject *self, PyObject *args)
8 | {
9 | int howMany;
10 | HCRYPTPROV hCryptProv;
11 | unsigned char* bytes = NULL;
12 | PyObject* returnVal = NULL;
13 |
14 |
15 | /* Read Arguments */
16 | if (!PyArg_ParseTuple(args, "i", &howMany))
17 | return(NULL);
18 |
19 | /* Get Context */
20 | if(CryptAcquireContext(
21 | &hCryptProv,
22 | NULL,
23 | NULL,
24 | PROV_RSA_FULL,
25 | CRYPT_VERIFYCONTEXT) == 0)
26 | return Py_BuildValue("s#", NULL, 0);
27 |
28 |
29 | /* Allocate bytes */
30 | bytes = malloc(howMany);
31 |
32 |
33 | /* Get random data */
34 | if(CryptGenRandom(
35 | hCryptProv,
36 | howMany,
37 | bytes) == 0)
38 | returnVal = Py_BuildValue("s#", NULL, 0);
39 | else
40 | returnVal = Py_BuildValue("s#", bytes, howMany);
41 |
42 | free(bytes);
43 | CryptReleaseContext(hCryptProv, 0);
44 |
45 | return returnVal;
46 | }
47 |
48 |
49 |
50 | /* List of functions exported by this module */
51 |
52 | static struct PyMethodDef win32prng_functions[] = {
53 | {"getRandomBytes", (PyCFunction)getRandomBytes, METH_VARARGS},
54 | {NULL, NULL} /* Sentinel */
55 | };
56 |
57 |
58 | /* Initialize this module. */
59 |
60 | DL_EXPORT(void) initwin32prng(void)
61 | {
62 | Py_InitModule("win32prng", win32prng_functions);
63 | }
64 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/Cryptlib_AES.py:
--------------------------------------------------------------------------------
1 | """Cryptlib AES implementation."""
2 |
3 | from cryptomath import *
4 | from AES import *
5 |
6 | if cryptlibpyLoaded:
7 |
8 | def new(key, mode, IV):
9 | return Cryptlib_AES(key, mode, IV)
10 |
11 | class Cryptlib_AES(AES):
12 |
13 | def __init__(self, key, mode, IV):
14 | AES.__init__(self, key, mode, IV, "cryptlib")
15 | self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_AES)
16 | cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_MODE, cryptlib_py.CRYPT_MODE_CBC)
17 | cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key))
18 | cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key)
19 | cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_IV, IV)
20 |
21 | def __del__(self):
22 | cryptlib_py.cryptDestroyContext(self.context)
23 |
24 | def encrypt(self, plaintext):
25 | AES.encrypt(self, plaintext)
26 | bytes = stringToBytes(plaintext)
27 | cryptlib_py.cryptEncrypt(self.context, bytes)
28 | return bytesToString(bytes)
29 |
30 | def decrypt(self, ciphertext):
31 | AES.decrypt(self, ciphertext)
32 | bytes = stringToBytes(ciphertext)
33 | cryptlib_py.cryptDecrypt(self.context, bytes)
34 | return bytesToString(bytes)
35 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/Cryptlib_TripleDES.py:
--------------------------------------------------------------------------------
1 | """Cryptlib 3DES implementation."""
2 |
3 | from cryptomath import *
4 |
5 | from TripleDES import *
6 |
7 | if cryptlibpyLoaded:
8 |
9 | def new(key, mode, IV):
10 | return Cryptlib_TripleDES(key, mode, IV)
11 |
12 | class Cryptlib_TripleDES(TripleDES):
13 |
14 | def __init__(self, key, mode, IV):
15 | TripleDES.__init__(self, key, mode, IV, "cryptlib")
16 | self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_3DES)
17 | cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_MODE, cryptlib_py.CRYPT_MODE_CBC)
18 | cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key))
19 | cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key)
20 | cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_IV, IV)
21 |
22 | def __del__(self):
23 | cryptlib_py.cryptDestroyContext(self.context)
24 |
25 | def encrypt(self, plaintext):
26 | TripleDES.encrypt(self, plaintext)
27 | bytes = stringToBytes(plaintext)
28 | cryptlib_py.cryptEncrypt(self.context, bytes)
29 | return bytesToString(bytes)
30 |
31 | def decrypt(self, ciphertext):
32 | TripleDES.decrypt(self, ciphertext)
33 | bytes = stringToBytes(ciphertext)
34 | cryptlib_py.cryptDecrypt(self.context, bytes)
35 | return bytesToString(bytes)
--------------------------------------------------------------------------------
/intercom/README.md:
--------------------------------------------------------------------------------
1 | # Twilio Intercom
2 |
3 | Does your company use Google Apps for email and documents? If so, you can deploy a web-based intercom system, based on Twilio Client, in just minutes. The most difficult part is getting authentication keys from Google.
4 |
5 | ## Getting Your Users
6 |
7 | For Twilio Intercom to work, it needs two pieces of information to work: the current user and the list of all memebers in your company. The latter is handled by `organization.py`.
8 |
9 | ## Google Apps
10 |
11 | The default implementation of `organization.py` uses the [Google Apps Data API](http://code.google.com/googleapps/domain/gdata_provisioning_api_v2.0_developers_protocol.html) to get the necessary information. To access this API, you'll need to jump through some hoops on Google's end of things to allow Intercom access to your organization's members.
12 |
13 | ### Google Apps and OAuth
14 |
15 | The `gdata` libraries use OAuth to authenticate client API calls. First, you'll need to log into your Google Apps dashboard.
16 |
17 | Navigate to **Advanced Options > Manage OAuth domain key third party**
18 |
19 | Check both boxes on the page: one next to **Enable this consumer key** and the other next to **Allow access to all APIs**.
20 |
21 | Navigate to **Advanced Options > Manage third party OAuth Client access**
22 |
23 | Under Client Name, add `your-domain.com` and under One or More API Scopes, add the two feeds like this: `https://apps-apis.google.com/a/feeds/group/#readonly,https://apps-apis.google.com/a/feeds/user/#readonly`
24 |
25 | Finally, fill in **OAuth consumer secret** and **OAuth consumer key** values in `organization.py` to finish up
26 |
--------------------------------------------------------------------------------
/intercom/gdata/notebook/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Google Notebook Data API"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 | import atom.data
25 | import gdata.data
26 | import gdata.opensearch.data
27 |
28 |
29 | NB_TEMPLATE = '{http://schemas.google.com/notes/2008/}%s'
30 |
31 |
32 | class ComesAfter(atom.core.XmlElement):
33 | """Preceding element."""
34 | _qname = NB_TEMPLATE % 'comesAfter'
35 | id = 'id'
36 |
37 |
38 | class NoteEntry(gdata.data.GDEntry):
39 | """Describes a note entry in the feed of a user's notebook."""
40 |
41 |
42 | class NotebookFeed(gdata.data.GDFeed):
43 | """Describes a notebook feed."""
44 | entry = [NoteEntry]
45 |
46 |
47 | class NotebookListEntry(gdata.data.GDEntry):
48 | """Describes a note list entry in the feed of a user's list of public notebooks."""
49 |
50 |
51 | class NotebookListFeed(gdata.data.GDFeed):
52 | """Describes a notebook list feed."""
53 | entry = [NotebookListEntry]
54 |
55 |
56 |
--------------------------------------------------------------------------------
/intercom/gdata/opensearch/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
18 | """Contains the data classes of the OpenSearch Extension"""
19 |
20 |
21 | __author__ = 'j.s@google.com (Jeff Scudder)'
22 |
23 |
24 | import atom.core
25 |
26 |
27 | OPENSEARCH_TEMPLATE_V1 = '{http://a9.com/-/spec/opensearchrss/1.0//}%s'
28 | OPENSEARCH_TEMPLATE_V2 = '{http://a9.com/-/spec/opensearch/1.1//}%s'
29 |
30 |
31 | class ItemsPerPage(atom.core.XmlElement):
32 | """Describes the number of items that will be returned per page for paged feeds"""
33 | _qname = (OPENSEARCH_TEMPLATE_V1 % 'itemsPerPage',
34 | OPENSEARCH_TEMPLATE_V2 % 'itemsPerPage')
35 |
36 |
37 | class StartIndex(atom.core.XmlElement):
38 | """Describes the starting index of the contained entries for paged feeds"""
39 | _qname = (OPENSEARCH_TEMPLATE_V1 % 'startIndex',
40 | OPENSEARCH_TEMPLATE_V2 % 'startIndex')
41 |
42 |
43 | class TotalResults(atom.core.XmlElement):
44 | """Describes the total number of results associated with this feed"""
45 | _qname = (OPENSEARCH_TEMPLATE_V1 % 'totalResults',
46 | OPENSEARCH_TEMPLATE_V2 % 'totalResults')
47 |
48 |
49 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/OpenSSL_TripleDES.py:
--------------------------------------------------------------------------------
1 | """OpenSSL/M2Crypto 3DES implementation."""
2 |
3 | from cryptomath import *
4 | from TripleDES import *
5 |
6 | if m2cryptoLoaded:
7 |
8 | def new(key, mode, IV):
9 | return OpenSSL_TripleDES(key, mode, IV)
10 |
11 | class OpenSSL_TripleDES(TripleDES):
12 |
13 | def __init__(self, key, mode, IV):
14 | TripleDES.__init__(self, key, mode, IV, "openssl")
15 | self.key = key
16 | self.IV = IV
17 |
18 | def _createContext(self, encrypt):
19 | context = m2.cipher_ctx_new()
20 | cipherType = m2.des_ede3_cbc()
21 | m2.cipher_init(context, cipherType, self.key, self.IV, encrypt)
22 | return context
23 |
24 | def encrypt(self, plaintext):
25 | TripleDES.encrypt(self, plaintext)
26 | context = self._createContext(1)
27 | ciphertext = m2.cipher_update(context, plaintext)
28 | m2.cipher_ctx_free(context)
29 | self.IV = ciphertext[-self.block_size:]
30 | return ciphertext
31 |
32 | def decrypt(self, ciphertext):
33 | TripleDES.decrypt(self, ciphertext)
34 | context = self._createContext(0)
35 | #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in.
36 | #To work around this, we append sixteen zeros to the string, below:
37 | plaintext = m2.cipher_update(context, ciphertext+('\0'*16))
38 |
39 | #If this bug is ever fixed, then plaintext will end up having a garbage
40 | #plaintext block on the end. That's okay - the below code will ignore it.
41 | plaintext = plaintext[:len(ciphertext)]
42 | m2.cipher_ctx_free(context)
43 | self.IV = ciphertext[-self.block_size:]
44 | return plaintext
--------------------------------------------------------------------------------
/intercom/gdata/acl/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Google Access Control List (ACL) Extension"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 | import atom.data
25 | import gdata.data
26 | import gdata.opensearch.data
27 |
28 |
29 | GACL_TEMPLATE = '{http://schemas.google.com/acl/2007}%s'
30 |
31 |
32 | class AclRole(atom.core.XmlElement):
33 | """Describes the role of an entry in an access control list."""
34 | _qname = GACL_TEMPLATE % 'role'
35 | value = 'value'
36 |
37 |
38 | class AclScope(atom.core.XmlElement):
39 | """Describes the scope of an entry in an access control list."""
40 | _qname = GACL_TEMPLATE % 'scope'
41 | type = 'type'
42 | value = 'value'
43 |
44 |
45 | class AclWithKey(atom.core.XmlElement):
46 | """Describes a key that can be used to access a document."""
47 | _qname = GACL_TEMPLATE % 'withKey'
48 | key = 'key'
49 | role = AclRole
50 |
51 |
52 | class AclEntry(gdata.data.GDEntry):
53 | """Describes an entry in a feed of an access control list (ACL)."""
54 | scope = AclScope
55 | role = AclRole
56 | with_key = AclWithKey
57 |
58 |
59 | class AclFeed(gdata.data.GDFeed):
60 | """Describes a feed of an access control list (ACL)."""
61 | entry = [AclEntry]
62 |
63 |
64 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/OpenSSL_AES.py:
--------------------------------------------------------------------------------
1 | """OpenSSL/M2Crypto AES implementation."""
2 |
3 | from cryptomath import *
4 | from AES import *
5 |
6 | if m2cryptoLoaded:
7 |
8 | def new(key, mode, IV):
9 | return OpenSSL_AES(key, mode, IV)
10 |
11 | class OpenSSL_AES(AES):
12 |
13 | def __init__(self, key, mode, IV):
14 | AES.__init__(self, key, mode, IV, "openssl")
15 | self.key = key
16 | self.IV = IV
17 |
18 | def _createContext(self, encrypt):
19 | context = m2.cipher_ctx_new()
20 | if len(self.key)==16:
21 | cipherType = m2.aes_128_cbc()
22 | if len(self.key)==24:
23 | cipherType = m2.aes_192_cbc()
24 | if len(self.key)==32:
25 | cipherType = m2.aes_256_cbc()
26 | m2.cipher_init(context, cipherType, self.key, self.IV, encrypt)
27 | return context
28 |
29 | def encrypt(self, plaintext):
30 | AES.encrypt(self, plaintext)
31 | context = self._createContext(1)
32 | ciphertext = m2.cipher_update(context, plaintext)
33 | m2.cipher_ctx_free(context)
34 | self.IV = ciphertext[-self.block_size:]
35 | return ciphertext
36 |
37 | def decrypt(self, ciphertext):
38 | AES.decrypt(self, ciphertext)
39 | context = self._createContext(0)
40 | #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in.
41 | #To work around this, we append sixteen zeros to the string, below:
42 | plaintext = m2.cipher_update(context, ciphertext+('\0'*16))
43 |
44 | #If this bug is ever fixed, then plaintext will end up having a garbage
45 | #plaintext block on the end. That's okay - the below code will discard it.
46 | plaintext = plaintext[:len(ciphertext)]
47 | m2.cipher_ctx_free(context)
48 | self.IV = ciphertext[-self.block_size:]
49 | return plaintext
50 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/integration/IntegrationHelper.py:
--------------------------------------------------------------------------------
1 |
2 | class IntegrationHelper:
3 |
4 | def __init__(self,
5 | username=None, password=None, sharedKey=None,
6 | certChain=None, privateKey=None,
7 | cryptoID=None, protocol=None,
8 | x509Fingerprint=None,
9 | x509TrustList=None, x509CommonName=None,
10 | settings = None):
11 |
12 | self.username = None
13 | self.password = None
14 | self.sharedKey = None
15 | self.certChain = None
16 | self.privateKey = None
17 | self.checker = None
18 |
19 | #SRP Authentication
20 | if username and password and not \
21 | (sharedKey or certChain or privateKey):
22 | self.username = username
23 | self.password = password
24 |
25 | #Shared Key Authentication
26 | elif username and sharedKey and not \
27 | (password or certChain or privateKey):
28 | self.username = username
29 | self.sharedKey = sharedKey
30 |
31 | #Certificate Chain Authentication
32 | elif certChain and privateKey and not \
33 | (username or password or sharedKey):
34 | self.certChain = certChain
35 | self.privateKey = privateKey
36 |
37 | #No Authentication
38 | elif not password and not username and not \
39 | sharedKey and not certChain and not privateKey:
40 | pass
41 |
42 | else:
43 | raise ValueError("Bad parameters")
44 |
45 | #Authenticate the server based on its cryptoID or fingerprint
46 | if sharedKey and (cryptoID or protocol or x509Fingerprint):
47 | raise ValueError("Can't use shared keys with other forms of"\
48 | "authentication")
49 |
50 | self.checker = Checker(cryptoID, protocol, x509Fingerprint,
51 | x509TrustList, x509CommonName)
52 | self.settings = settings
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/PyCrypto_RSAKey.py:
--------------------------------------------------------------------------------
1 | """PyCrypto RSA implementation."""
2 |
3 | from cryptomath import *
4 |
5 | from RSAKey import *
6 | from Python_RSAKey import Python_RSAKey
7 |
8 | if pycryptoLoaded:
9 |
10 | from Crypto.PublicKey import RSA
11 |
12 | class PyCrypto_RSAKey(RSAKey):
13 | def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
14 | if not d:
15 | self.rsa = RSA.construct( (n, e) )
16 | else:
17 | self.rsa = RSA.construct( (n, e, d, p, q) )
18 |
19 | def __getattr__(self, name):
20 | return getattr(self.rsa, name)
21 |
22 | def hasPrivateKey(self):
23 | return self.rsa.has_private()
24 |
25 | def hash(self):
26 | return Python_RSAKey(self.n, self.e).hash()
27 |
28 | def _rawPrivateKeyOp(self, m):
29 | s = numberToString(m)
30 | byteLength = numBytes(self.n)
31 | if len(s)== byteLength:
32 | pass
33 | elif len(s) == byteLength-1:
34 | s = '\0' + s
35 | else:
36 | raise AssertionError()
37 | c = stringToNumber(self.rsa.decrypt((s,)))
38 | return c
39 |
40 | def _rawPublicKeyOp(self, c):
41 | s = numberToString(c)
42 | byteLength = numBytes(self.n)
43 | if len(s)== byteLength:
44 | pass
45 | elif len(s) == byteLength-1:
46 | s = '\0' + s
47 | else:
48 | raise AssertionError()
49 | m = stringToNumber(self.rsa.encrypt(s, None)[0])
50 | return m
51 |
52 | def writeXMLPublicKey(self, indent=''):
53 | return Python_RSAKey(self.n, self.e).write(indent)
54 |
55 | def generate(bits):
56 | key = PyCrypto_RSAKey()
57 | def f(numBytes):
58 | return bytesToString(getRandomBytes(numBytes))
59 | key.rsa = RSA.generate(bits, f)
60 | return key
61 | generate = staticmethod(generate)
62 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/SharedKeyDB.py:
--------------------------------------------------------------------------------
1 | """Class for storing shared keys."""
2 |
3 | from utils.cryptomath import *
4 | from utils.compat import *
5 | from mathtls import *
6 | from Session import Session
7 | from BaseDB import BaseDB
8 |
9 | class SharedKeyDB(BaseDB):
10 | """This class represent an in-memory or on-disk database of shared
11 | keys.
12 |
13 | A SharedKeyDB can be passed to a server handshake function to
14 | authenticate a client based on one of the shared keys.
15 |
16 | This class is thread-safe.
17 | """
18 |
19 | def __init__(self, filename=None):
20 | """Create a new SharedKeyDB.
21 |
22 | @type filename: str
23 | @param filename: Filename for an on-disk database, or None for
24 | an in-memory database. If the filename already exists, follow
25 | this with a call to open(). To create a new on-disk database,
26 | follow this with a call to create().
27 | """
28 | BaseDB.__init__(self, filename, "shared key")
29 |
30 | def _getItem(self, username, valueStr):
31 | session = Session()
32 | session._createSharedKey(username, valueStr)
33 | return session
34 |
35 | def __setitem__(self, username, sharedKey):
36 | """Add a shared key to the database.
37 |
38 | @type username: str
39 | @param username: The username to associate the shared key with.
40 | Must be less than or equal to 16 characters in length, and must
41 | not already be in the database.
42 |
43 | @type sharedKey: str
44 | @param sharedKey: The shared key to add. Must be less than 48
45 | characters in length.
46 | """
47 | BaseDB.__setitem__(self, username, sharedKey)
48 |
49 | def _setItem(self, username, value):
50 | if len(username)>16:
51 | raise ValueError("username too long")
52 | if len(value)>=48:
53 | raise ValueError("shared key too long")
54 | return value
55 |
56 | def _checkItem(self, value, username, param):
57 | newSession = self._getItem(username, param)
58 | return value.masterSecret == newSession.masterSecret
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/Python_AES.py:
--------------------------------------------------------------------------------
1 | """Pure-Python AES implementation."""
2 |
3 | from cryptomath import *
4 |
5 | from AES import *
6 | from rijndael import rijndael
7 |
8 | def new(key, mode, IV):
9 | return Python_AES(key, mode, IV)
10 |
11 | class Python_AES(AES):
12 | def __init__(self, key, mode, IV):
13 | AES.__init__(self, key, mode, IV, "python")
14 | self.rijndael = rijndael(key, 16)
15 | self.IV = IV
16 |
17 | def encrypt(self, plaintext):
18 | AES.encrypt(self, plaintext)
19 |
20 | plaintextBytes = stringToBytes(plaintext)
21 | chainBytes = stringToBytes(self.IV)
22 |
23 | #CBC Mode: For each block...
24 | for x in range(len(plaintextBytes)/16):
25 |
26 | #XOR with the chaining block
27 | blockBytes = plaintextBytes[x*16 : (x*16)+16]
28 | for y in range(16):
29 | blockBytes[y] ^= chainBytes[y]
30 | blockString = bytesToString(blockBytes)
31 |
32 | #Encrypt it
33 | encryptedBytes = stringToBytes(self.rijndael.encrypt(blockString))
34 |
35 | #Overwrite the input with the output
36 | for y in range(16):
37 | plaintextBytes[(x*16)+y] = encryptedBytes[y]
38 |
39 | #Set the next chaining block
40 | chainBytes = encryptedBytes
41 |
42 | self.IV = bytesToString(chainBytes)
43 | return bytesToString(plaintextBytes)
44 |
45 | def decrypt(self, ciphertext):
46 | AES.decrypt(self, ciphertext)
47 |
48 | ciphertextBytes = stringToBytes(ciphertext)
49 | chainBytes = stringToBytes(self.IV)
50 |
51 | #CBC Mode: For each block...
52 | for x in range(len(ciphertextBytes)/16):
53 |
54 | #Decrypt it
55 | blockBytes = ciphertextBytes[x*16 : (x*16)+16]
56 | blockString = bytesToString(blockBytes)
57 | decryptedBytes = stringToBytes(self.rijndael.decrypt(blockString))
58 |
59 | #XOR with the chaining block and overwrite the input with output
60 | for y in range(16):
61 | decryptedBytes[y] ^= chainBytes[y]
62 | ciphertextBytes[(x*16)+y] = decryptedBytes[y]
63 |
64 | #Set the next chaining block
65 | chainBytes = blockBytes
66 |
67 | self.IV = bytesToString(chainBytes)
68 | return bytesToString(ciphertextBytes)
69 |
--------------------------------------------------------------------------------
/intercom/gdata/dublincore/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Dublin Core Metadata Initiative (DCMI) Extension"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 |
25 |
26 | DC_TEMPLATE = '{http://purl.org/dc/terms/}%s'
27 |
28 |
29 | class Creator(atom.core.XmlElement):
30 | """Entity primarily responsible for making the resource."""
31 | _qname = DC_TEMPLATE % 'creator'
32 |
33 |
34 | class Date(atom.core.XmlElement):
35 | """Point or period of time associated with an event in the lifecycle of the resource."""
36 | _qname = DC_TEMPLATE % 'date'
37 |
38 |
39 | class Description(atom.core.XmlElement):
40 | """Account of the resource."""
41 | _qname = DC_TEMPLATE % 'description'
42 |
43 |
44 | class Format(atom.core.XmlElement):
45 | """File format, physical medium, or dimensions of the resource."""
46 | _qname = DC_TEMPLATE % 'format'
47 |
48 |
49 | class Identifier(atom.core.XmlElement):
50 | """An unambiguous reference to the resource within a given context."""
51 | _qname = DC_TEMPLATE % 'identifier'
52 |
53 |
54 | class Language(atom.core.XmlElement):
55 | """Language of the resource."""
56 | _qname = DC_TEMPLATE % 'language'
57 |
58 |
59 | class Publisher(atom.core.XmlElement):
60 | """Entity responsible for making the resource available."""
61 | _qname = DC_TEMPLATE % 'publisher'
62 |
63 |
64 | class Rights(atom.core.XmlElement):
65 | """Information about rights held in and over the resource."""
66 | _qname = DC_TEMPLATE % 'rights'
67 |
68 |
69 | class Subject(atom.core.XmlElement):
70 | """Topic of the resource."""
71 | _qname = DC_TEMPLATE % 'subject'
72 |
73 |
74 | class Title(atom.core.XmlElement):
75 | """Name given to the resource."""
76 | _qname = DC_TEMPLATE % 'title'
77 |
78 |
79 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/integration/TLSSocketServerMixIn.py:
--------------------------------------------------------------------------------
1 | """TLS Lite + SocketServer."""
2 |
3 | from gdata.tlslite.TLSConnection import TLSConnection
4 |
5 | class TLSSocketServerMixIn:
6 | """
7 | This class can be mixed in with any L{SocketServer.TCPServer} to
8 | add TLS support.
9 |
10 | To use this class, define a new class that inherits from it and
11 | some L{SocketServer.TCPServer} (with the mix-in first). Then
12 | implement the handshake() method, doing some sort of server
13 | handshake on the connection argument. If the handshake method
14 | returns True, the RequestHandler will be triggered. Below is a
15 | complete example of a threaded HTTPS server::
16 |
17 | from SocketServer import *
18 | from BaseHTTPServer import *
19 | from SimpleHTTPServer import *
20 | from tlslite.api import *
21 |
22 | s = open("./serverX509Cert.pem").read()
23 | x509 = X509()
24 | x509.parse(s)
25 | certChain = X509CertChain([x509])
26 |
27 | s = open("./serverX509Key.pem").read()
28 | privateKey = parsePEMKey(s, private=True)
29 |
30 | sessionCache = SessionCache()
31 |
32 | class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn,
33 | HTTPServer):
34 | def handshake(self, tlsConnection):
35 | try:
36 | tlsConnection.handshakeServer(certChain=certChain,
37 | privateKey=privateKey,
38 | sessionCache=sessionCache)
39 | tlsConnection.ignoreAbruptClose = True
40 | return True
41 | except TLSError, error:
42 | print "Handshake failure:", str(error)
43 | return False
44 |
45 | httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
46 | httpd.serve_forever()
47 | """
48 |
49 |
50 | def finish_request(self, sock, client_address):
51 | tlsConnection = TLSConnection(sock)
52 | if self.handshake(tlsConnection) == True:
53 | self.RequestHandlerClass(tlsConnection, client_address, self)
54 | tlsConnection.close()
55 |
56 | #Implement this method to do some form of handshaking. Return True
57 | #if the handshake finishes properly and the request is authorized.
58 | def handshake(self, tlsConnection):
59 | raise NotImplementedError()
60 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/dateFuncs.py:
--------------------------------------------------------------------------------
1 |
2 | import os
3 |
4 | #Functions for manipulating datetime objects
5 | #CCYY-MM-DDThh:mm:ssZ
6 | def parseDateClass(s):
7 | year, month, day = s.split("-")
8 | day, tail = day[:2], day[2:]
9 | hour, minute, second = tail[1:].split(":")
10 | second = second[:2]
11 | year, month, day = int(year), int(month), int(day)
12 | hour, minute, second = int(hour), int(minute), int(second)
13 | return createDateClass(year, month, day, hour, minute, second)
14 |
15 |
16 | if os.name != "java":
17 | from datetime import datetime, timedelta
18 |
19 | #Helper functions for working with a date/time class
20 | def createDateClass(year, month, day, hour, minute, second):
21 | return datetime(year, month, day, hour, minute, second)
22 |
23 | def printDateClass(d):
24 | #Split off fractional seconds, append 'Z'
25 | return d.isoformat().split(".")[0]+"Z"
26 |
27 | def getNow():
28 | return datetime.utcnow()
29 |
30 | def getHoursFromNow(hours):
31 | return datetime.utcnow() + timedelta(hours=hours)
32 |
33 | def getMinutesFromNow(minutes):
34 | return datetime.utcnow() + timedelta(minutes=minutes)
35 |
36 | def isDateClassExpired(d):
37 | return d < datetime.utcnow()
38 |
39 | def isDateClassBefore(d1, d2):
40 | return d1 < d2
41 |
42 | else:
43 | #Jython 2.1 is missing lots of python 2.3 stuff,
44 | #which we have to emulate here:
45 | import java
46 | import jarray
47 |
48 | def createDateClass(year, month, day, hour, minute, second):
49 | c = java.util.Calendar.getInstance()
50 | c.setTimeZone(java.util.TimeZone.getTimeZone("UTC"))
51 | c.set(year, month-1, day, hour, minute, second)
52 | return c
53 |
54 | def printDateClass(d):
55 | return "%04d-%02d-%02dT%02d:%02d:%02dZ" % \
56 | (d.get(d.YEAR), d.get(d.MONTH)+1, d.get(d.DATE), \
57 | d.get(d.HOUR_OF_DAY), d.get(d.MINUTE), d.get(d.SECOND))
58 |
59 | def getNow():
60 | c = java.util.Calendar.getInstance()
61 | c.setTimeZone(java.util.TimeZone.getTimeZone("UTC"))
62 | c.get(c.HOUR) #force refresh?
63 | return c
64 |
65 | def getHoursFromNow(hours):
66 | d = getNow()
67 | d.add(d.HOUR, hours)
68 | return d
69 |
70 | def isDateClassExpired(d):
71 | n = getNow()
72 | return d.before(n)
73 |
74 | def isDateClassBefore(d1, d2):
75 | return d1.before(d2)
76 |
--------------------------------------------------------------------------------
/intercom/twilio/contrib/jwt/__init__.py:
--------------------------------------------------------------------------------
1 | """ JSON Web Token implementation
2 |
3 | Minimum implementation based on this spec:
4 | http://self-issued.info/docs/draft-jones-json-web-token-01.html
5 | """
6 | import base64
7 | import hashlib
8 | import hmac
9 |
10 | try:
11 | import json
12 | except ImportError:
13 | import simplejson as json
14 |
15 | __all__ = ['encode', 'decode', 'DecodeError']
16 |
17 | class DecodeError(Exception): pass
18 |
19 | signing_methods = {
20 | 'HS256': lambda msg, key: hmac.new(key, msg, hashlib.sha256).digest(),
21 | 'HS384': lambda msg, key: hmac.new(key, msg, hashlib.sha384).digest(),
22 | 'HS512': lambda msg, key: hmac.new(key, msg, hashlib.sha512).digest(),
23 | }
24 |
25 | def base64url_decode(input):
26 | input += '=' * (4 - (len(input) % 4))
27 | return base64.urlsafe_b64decode(input)
28 |
29 | def base64url_encode(input):
30 | return base64.urlsafe_b64encode(input).replace('=', '')
31 |
32 | def header(jwt):
33 | header_segment = jwt.split('.', 1)[0]
34 | try:
35 | return json.loads(base64url_decode(header_segment))
36 | except (ValueError, TypeError):
37 | raise DecodeError("Invalid header encoding")
38 |
39 | def encode(payload, key, algorithm='HS256'):
40 | segments = []
41 | header = {"typ": "JWT", "alg": algorithm}
42 | segments.append(base64url_encode(json.dumps(header)))
43 | segments.append(base64url_encode(json.dumps(payload)))
44 | signing_input = '.'.join(segments)
45 | try:
46 | ascii_key = unicode(key).encode('utf8')
47 | signature = signing_methods[algorithm](signing_input, ascii_key)
48 | except KeyError:
49 | raise NotImplementedError("Algorithm not supported")
50 | segments.append(base64url_encode(signature))
51 | return '.'.join(segments)
52 |
53 | def decode(jwt, key='', verify=True):
54 | try:
55 | signing_input, crypto_segment = jwt.rsplit('.', 1)
56 | header_segment, payload_segment = signing_input.split('.', 1)
57 | except ValueError:
58 | raise DecodeError("Not enough segments")
59 | try:
60 | header = json.loads(base64url_decode(header_segment))
61 | payload = json.loads(base64url_decode(payload_segment))
62 | signature = base64url_decode(crypto_segment)
63 | except (ValueError, TypeError):
64 | raise DecodeError("Invalid segment encoding")
65 | if verify:
66 | try:
67 | ascii_key = unicode(key).encode('utf8')
68 | if not signature == signing_methods[header['alg']](signing_input, ascii_key):
69 | raise DecodeError("Signature verification failed")
70 | except KeyError:
71 | raise DecodeError("Algorithm not supported")
72 | return payload
73 |
--------------------------------------------------------------------------------
/intercom/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright 2007 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 | import os
18 | import organization
19 | import settings
20 | from django.utils import simplejson as json
21 | from google.appengine.api import users
22 | from google.appengine.ext import webapp
23 | from google.appengine.ext.webapp import template
24 | from google.appengine.ext.webapp import util
25 | from twilio.util import TwilioCapability
26 |
27 |
28 | class IntercomHandler(webapp.RequestHandler):
29 |
30 | def get(self, user_filter="all"):
31 |
32 | user = users.get_current_user()
33 | client_name = user.email().split("@")[0]
34 |
35 | capability = TwilioCapability(settings.ACCOUNT_SID,
36 | settings.AUTH_TOKEN)
37 | capability.allow_client_outgoing(settings.APP_SID)
38 | capability.allow_client_incoming(client_name)
39 |
40 | tp = {
41 | 'token': capability.generate(),
42 | "user_filter": user_filter,
43 | }
44 |
45 | path = os.path.join(os.path.dirname(__file__),
46 | 'templates', 'intercom.html')
47 | self.response.out.write(template.render(path, tp))
48 |
49 |
50 | class UsersHandler(webapp.RequestHandler):
51 |
52 | def get(self):
53 | self.response.headers["Content-Type"] = "application/json"
54 | self.response.out.write(json.dumps(organization.users()))
55 |
56 |
57 | class TwimlHandler(webapp.RequestHandler):
58 |
59 | def get(self):
60 | tp = {"client": self.request.get("Person")}
61 |
62 | self.response.headers["Content-Type"] = "application/xml"
63 | path = os.path.join(os.path.dirname(__file__),
64 | 'templates', 'twiml.html')
65 | self.response.out.write(template.render(path, tp))
66 |
67 | def post(self):
68 | self.get()
69 |
70 |
71 | def main():
72 | application = webapp.WSGIApplication([
73 | ('/(available|unavailable)?', IntercomHandler),
74 | ('/users', UsersHandler),
75 | ('/call', TwimlHandler),
76 | ], debug=True)
77 | util.run_wsgi_app(application)
78 |
79 |
80 | if __name__ == '__main__':
81 | main()
82 |
--------------------------------------------------------------------------------
/intercom/gdata/geo/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Geography Extension"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 |
25 |
26 | GEORSS_TEMPLATE = '{http://www.georss.org/georss/}%s'
27 | GML_TEMPLATE = '{http://www.opengis.net/gml/}%s'
28 | GEO_TEMPLATE = '{http://www.w3.org/2003/01/geo/wgs84_pos#/}%s'
29 |
30 |
31 | class GeoLat(atom.core.XmlElement):
32 | """Describes a W3C latitude."""
33 | _qname = GEO_TEMPLATE % 'lat'
34 |
35 |
36 | class GeoLong(atom.core.XmlElement):
37 | """Describes a W3C longitude."""
38 | _qname = GEO_TEMPLATE % 'long'
39 |
40 |
41 | class GeoRssBox(atom.core.XmlElement):
42 | """Describes a geographical region."""
43 | _qname = GEORSS_TEMPLATE % 'box'
44 |
45 |
46 | class GeoRssPoint(atom.core.XmlElement):
47 | """Describes a geographical location."""
48 | _qname = GEORSS_TEMPLATE % 'point'
49 |
50 |
51 | class GmlLowerCorner(atom.core.XmlElement):
52 | """Describes a lower corner of a region."""
53 | _qname = GML_TEMPLATE % 'lowerCorner'
54 |
55 |
56 | class GmlPos(atom.core.XmlElement):
57 | """Describes a latitude and longitude."""
58 | _qname = GML_TEMPLATE % 'pos'
59 |
60 |
61 | class GmlPoint(atom.core.XmlElement):
62 | """Describes a particular geographical point."""
63 | _qname = GML_TEMPLATE % 'Point'
64 | pos = GmlPos
65 |
66 |
67 | class GmlUpperCorner(atom.core.XmlElement):
68 | """Describes an upper corner of a region."""
69 | _qname = GML_TEMPLATE % 'upperCorner'
70 |
71 |
72 | class GmlEnvelope(atom.core.XmlElement):
73 | """Describes a Gml geographical region."""
74 | _qname = GML_TEMPLATE % 'Envelope'
75 | lower_corner = GmlLowerCorner
76 | upper_corner = GmlUpperCorner
77 |
78 |
79 | class GeoRssWhere(atom.core.XmlElement):
80 | """Describes a geographical location or region."""
81 | _qname = GEORSS_TEMPLATE % 'where'
82 | Point = GmlPoint
83 | Envelope = GmlEnvelope
84 |
85 |
86 | class W3CPoint(atom.core.XmlElement):
87 | """Describes a W3C geographical location."""
88 | _qname = GEO_TEMPLATE % 'Point'
89 | long = GeoLong
90 | lat = GeoLat
91 |
92 |
93 |
--------------------------------------------------------------------------------
/intercom/gdata/books/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Google Book Search Data API"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 | import atom.data
25 | import gdata.data
26 | import gdata.dublincore.data
27 | import gdata.opensearch.data
28 |
29 |
30 | GBS_TEMPLATE = '{http://schemas.google.com/books/2008/}%s'
31 |
32 |
33 | class CollectionEntry(gdata.data.GDEntry):
34 | """Describes an entry in a feed of collections."""
35 |
36 |
37 | class CollectionFeed(gdata.data.BatchFeed):
38 | """Describes a Book Search collection feed."""
39 | entry = [CollectionEntry]
40 |
41 |
42 | class Embeddability(atom.core.XmlElement):
43 | """Describes an embeddability."""
44 | _qname = GBS_TEMPLATE % 'embeddability'
45 | value = 'value'
46 |
47 |
48 | class OpenAccess(atom.core.XmlElement):
49 | """Describes an open access."""
50 | _qname = GBS_TEMPLATE % 'openAccess'
51 | value = 'value'
52 |
53 |
54 | class Review(atom.core.XmlElement):
55 | """User-provided review."""
56 | _qname = GBS_TEMPLATE % 'review'
57 | lang = 'lang'
58 | type = 'type'
59 |
60 |
61 | class Viewability(atom.core.XmlElement):
62 | """Describes a viewability."""
63 | _qname = GBS_TEMPLATE % 'viewability'
64 | value = 'value'
65 |
66 |
67 | class VolumeEntry(gdata.data.GDEntry):
68 | """Describes an entry in a feed of Book Search volumes."""
69 | comments = gdata.data.Comments
70 | language = [gdata.dublincore.data.Language]
71 | open_access = OpenAccess
72 | format = [gdata.dublincore.data.Format]
73 | dc_title = [gdata.dublincore.data.Title]
74 | viewability = Viewability
75 | embeddability = Embeddability
76 | creator = [gdata.dublincore.data.Creator]
77 | rating = gdata.data.Rating
78 | description = [gdata.dublincore.data.Description]
79 | publisher = [gdata.dublincore.data.Publisher]
80 | date = [gdata.dublincore.data.Date]
81 | subject = [gdata.dublincore.data.Subject]
82 | identifier = [gdata.dublincore.data.Identifier]
83 | review = Review
84 |
85 |
86 | class VolumeFeed(gdata.data.BatchFeed):
87 | """Describes a Book Search volume feed."""
88 | entry = [VolumeEntry]
89 |
90 |
91 |
--------------------------------------------------------------------------------
/intercom/static/css/intercom.css:
--------------------------------------------------------------------------------
1 | h1, h2, h3, h4, h5, h6, ul{
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | background: #111 url("../images/padded.png");
8 | }
9 |
10 | #wrapper {
11 | background: transparent;
12 | display: -webkit-box;
13 | -webkit-box-orient: vertical;
14 | -webkit-box-align: center;
15 | position: absolute;
16 | top: 0px;
17 | bottom: 0px;
18 | left: 0px;
19 | right: 0px;
20 | }
21 |
22 | section {
23 | display: -webkit-box;
24 | -webkit-box-orient: vertical;
25 | max-width: 400px;
26 | width: 100%;
27 | background: #FFF;
28 | color: #111;
29 | -webkit-box-flex: 1;
30 | }
31 |
32 | section > header h1{
33 | text-align: left;
34 | }
35 |
36 | section > ul {
37 | overflow-y: auto;
38 | -webkit-box-flex: 1;
39 | }
40 |
41 |
42 | section > footer h1 {
43 | -webkit-box-flex: 1;
44 | text-align: left;
45 | }
46 |
47 | section > footer {
48 | display: -webkit-box;
49 | -webkit-box-align: center;
50 | padding: 15px;
51 | border-top: 1px solid #aaa;
52 | }
53 |
54 | section > footer > button{
55 | border: 1px solid #aaa !important;
56 | }
57 |
58 | header {
59 | display: -webkit-box;
60 | -webkit-box-align: center;
61 | border-bottom: 1px solid #aaa;
62 | }
63 |
64 | header, footer {
65 | padding: 15px;
66 | text-align: center;
67 | display: -webkit-box;
68 | -webkit-box-align: center;
69 | background: #efefef; /* Old browsers */
70 | background: -moz-linear-gradient(top, #efefef 0%, #bcbcbc 100%); /* FF3.6+ */
71 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#efefef), color-stop(100%,#bcbcbc)); /* Chrome,Safari4+ */
72 | background: -webkit-linear-gradient(top, #efefef 0%,#bcbcbc 100%); /* Chrome10+,Safari5.1+ */
73 | background: -o-linear-gradient(top, #efefef 0%,#bcbcbc 100%); /* Opera11.10+ */
74 | background: -ms-linear-gradient(top, #efefef 0%,#bcbcbc 100%); /* IE10+ */
75 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#efefef', endColorstr='#bcbcbc',GradientType=0 ); /* IE6-9 */
76 | background: linear-gradient(top, #efefef 0%,#bcbcbc 100%); /* W3C */
77 | }
78 |
79 | header h1, header aside {
80 | -webkit-box-flex: 1;
81 | }
82 |
83 | ul li {
84 | padding: 10px 15px;
85 | display: -webkit-box;
86 | -webkit-box-align: center;
87 | border-bottom: 1px solid #ddd;
88 | }
89 |
90 | ul li button, ul li span {
91 | display: block;
92 | }
93 |
94 | ul li button {
95 | width: 50px;
96 | margin-left: 10px;
97 | }
98 |
99 | ul li span {
100 | -webkit-box-flex: 1;
101 | }
102 |
103 | ul li div {
104 | margin-right: 10px;
105 | width: 10px;
106 | height: 10px;
107 | border-radius: 100px;
108 | border-width: 1px;
109 | border-style: solid;
110 | }
111 |
112 | div.unavailable {
113 | background: #ccc;
114 | border-color: #aaa;
115 | }
116 |
117 | div.available {
118 | background: #8ee63b;
119 | border-color: #6ab601;
120 | }
121 |
122 | select option {
123 | text-transform:capitalize;
124 | }
125 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/codec.py:
--------------------------------------------------------------------------------
1 | """Classes for reading/writing binary data (such as TLS records)."""
2 |
3 | from compat import *
4 |
5 | class Writer:
6 | def __init__(self, length=0):
7 | #If length is zero, then this is just a "trial run" to determine length
8 | self.index = 0
9 | self.bytes = createByteArrayZeros(length)
10 |
11 | def add(self, x, length):
12 | if self.bytes:
13 | newIndex = self.index+length-1
14 | while newIndex >= self.index:
15 | self.bytes[newIndex] = x & 0xFF
16 | x >>= 8
17 | newIndex -= 1
18 | self.index += length
19 |
20 | def addFixSeq(self, seq, length):
21 | if self.bytes:
22 | for e in seq:
23 | self.add(e, length)
24 | else:
25 | self.index += len(seq)*length
26 |
27 | def addVarSeq(self, seq, length, lengthLength):
28 | if self.bytes:
29 | self.add(len(seq)*length, lengthLength)
30 | for e in seq:
31 | self.add(e, length)
32 | else:
33 | self.index += lengthLength + (len(seq)*length)
34 |
35 |
36 | class Parser:
37 | def __init__(self, bytes):
38 | self.bytes = bytes
39 | self.index = 0
40 |
41 | def get(self, length):
42 | if self.index + length > len(self.bytes):
43 | raise SyntaxError()
44 | x = 0
45 | for count in range(length):
46 | x <<= 8
47 | x |= self.bytes[self.index]
48 | self.index += 1
49 | return x
50 |
51 | def getFixBytes(self, lengthBytes):
52 | bytes = self.bytes[self.index : self.index+lengthBytes]
53 | self.index += lengthBytes
54 | return bytes
55 |
56 | def getVarBytes(self, lengthLength):
57 | lengthBytes = self.get(lengthLength)
58 | return self.getFixBytes(lengthBytes)
59 |
60 | def getFixList(self, length, lengthList):
61 | l = [0] * lengthList
62 | for x in range(lengthList):
63 | l[x] = self.get(length)
64 | return l
65 |
66 | def getVarList(self, length, lengthLength):
67 | lengthList = self.get(lengthLength)
68 | if lengthList % length != 0:
69 | raise SyntaxError()
70 | lengthList = int(lengthList/length)
71 | l = [0] * lengthList
72 | for x in range(lengthList):
73 | l[x] = self.get(length)
74 | return l
75 |
76 | def startLengthCheck(self, lengthLength):
77 | self.lengthCheck = self.get(lengthLength)
78 | self.indexCheck = self.index
79 |
80 | def setLengthCheck(self, length):
81 | self.lengthCheck = length
82 | self.indexCheck = self.index
83 |
84 | def stopLengthCheck(self):
85 | if (self.index - self.indexCheck) != self.lengthCheck:
86 | raise SyntaxError()
87 |
88 | def atLengthCheck(self):
89 | if (self.index - self.indexCheck) < self.lengthCheck:
90 | return False
91 | elif (self.index - self.indexCheck) == self.lengthCheck:
92 | return True
93 | else:
94 | raise SyntaxError()
--------------------------------------------------------------------------------
/intercom/gdata/marketplace/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2009 Google Inc. All Rights Reserved.
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 | """Data model for parsing and generating XML for the Google Apps Marketplace Licensing API."""
18 |
19 |
20 | __author__ = 'Alexandre Vivien '
21 |
22 |
23 | import atom.core
24 | import gdata
25 | import gdata.data
26 |
27 |
28 | LICENSES_NAMESPACE = 'http://www.w3.org/2005/Atom'
29 | LICENSES_TEMPLATE = '{%s}%%s' % LICENSES_NAMESPACE
30 |
31 |
32 | class Enabled(atom.core.XmlElement):
33 | """ """
34 |
35 | _qname = LICENSES_TEMPLATE % 'enabled'
36 |
37 |
38 | class Id(atom.core.XmlElement):
39 | """ """
40 |
41 | _qname = LICENSES_TEMPLATE % 'id'
42 |
43 |
44 | class CustomerId(atom.core.XmlElement):
45 | """ """
46 |
47 | _qname = LICENSES_TEMPLATE % 'customerid'
48 |
49 |
50 | class DomainName(atom.core.XmlElement):
51 | """ """
52 |
53 | _qname = LICENSES_TEMPLATE % 'domainname'
54 |
55 |
56 | class InstallerEmail(atom.core.XmlElement):
57 | """ """
58 |
59 | _qname = LICENSES_TEMPLATE % 'installeremail'
60 |
61 |
62 | class TosAcceptanceTime(atom.core.XmlElement):
63 | """ """
64 |
65 | _qname = LICENSES_TEMPLATE % 'tosacceptancetime'
66 |
67 |
68 | class LastChangeTime(atom.core.XmlElement):
69 | """ """
70 |
71 | _qname = LICENSES_TEMPLATE % 'lastchangetime'
72 |
73 |
74 | class ProductConfigId(atom.core.XmlElement):
75 | """ """
76 |
77 | _qname = LICENSES_TEMPLATE % 'productconfigid'
78 |
79 |
80 | class State(atom.core.XmlElement):
81 | """ """
82 |
83 | _qname = LICENSES_TEMPLATE % 'state'
84 |
85 |
86 | class Entity(atom.core.XmlElement):
87 | """ The entity representing the License. """
88 |
89 | _qname = LICENSES_TEMPLATE % 'entity'
90 |
91 | enabled = Enabled
92 | id = Id
93 | customer_id = CustomerId
94 | domain_name = DomainName
95 | installer_email = InstallerEmail
96 | tos_acceptance_time = TosAcceptanceTime
97 | last_change_time = LastChangeTime
98 | product_config_id = ProductConfigId
99 | state = State
100 |
101 |
102 | class Content(atom.data.Content):
103 | entity = Entity
104 |
105 | class LicenseEntry(gdata.data.GDEntry):
106 | """ Represents a LicenseEntry object. """
107 |
108 | content = Content
109 |
110 |
111 | class LicenseFeed(gdata.data.GDFeed):
112 | """ Represents a feed of LicenseEntry objects. """
113 |
114 | # Override entry so that this feed knows how to type its list of entries.
115 | entry = [LicenseEntry]
116 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/api.py:
--------------------------------------------------------------------------------
1 | """Import this module for easy access to TLS Lite objects.
2 |
3 | The TLS Lite API consists of classes, functions, and variables spread
4 | throughout this package. Instead of importing them individually with::
5 |
6 | from tlslite.TLSConnection import TLSConnection
7 | from tlslite.HandshakeSettings import HandshakeSettings
8 | from tlslite.errors import *
9 | .
10 | .
11 |
12 | It's easier to do::
13 |
14 | from tlslite.api import *
15 |
16 | This imports all the important objects (TLSConnection, Checker,
17 | HandshakeSettings, etc.) into the global namespace. In particular, it
18 | imports::
19 |
20 | from constants import AlertLevel, AlertDescription, Fault
21 | from errors import *
22 | from Checker import Checker
23 | from HandshakeSettings import HandshakeSettings
24 | from Session import Session
25 | from SessionCache import SessionCache
26 | from SharedKeyDB import SharedKeyDB
27 | from TLSConnection import TLSConnection
28 | from VerifierDB import VerifierDB
29 | from X509 import X509
30 | from X509CertChain import X509CertChain
31 |
32 | from integration.HTTPTLSConnection import HTTPTLSConnection
33 | from integration.POP3_TLS import POP3_TLS
34 | from integration.IMAP4_TLS import IMAP4_TLS
35 | from integration.SMTP_TLS import SMTP_TLS
36 | from integration.XMLRPCTransport import XMLRPCTransport
37 | from integration.TLSSocketServerMixIn import TLSSocketServerMixIn
38 | from integration.TLSAsyncDispatcherMixIn import TLSAsyncDispatcherMixIn
39 | from integration.TLSTwistedProtocolWrapper import TLSTwistedProtocolWrapper
40 | from utils.cryptomath import cryptlibpyLoaded, m2cryptoLoaded,
41 | gmpyLoaded, pycryptoLoaded, prngName
42 | from utils.keyfactory import generateRSAKey, parsePEMKey, parseXMLKey,
43 | parseAsPublicKey, parsePrivateKey
44 | """
45 |
46 | from constants import AlertLevel, AlertDescription, Fault
47 | from errors import *
48 | from Checker import Checker
49 | from HandshakeSettings import HandshakeSettings
50 | from Session import Session
51 | from SessionCache import SessionCache
52 | from SharedKeyDB import SharedKeyDB
53 | from TLSConnection import TLSConnection
54 | from VerifierDB import VerifierDB
55 | from X509 import X509
56 | from X509CertChain import X509CertChain
57 |
58 | from integration.HTTPTLSConnection import HTTPTLSConnection
59 | from integration.TLSSocketServerMixIn import TLSSocketServerMixIn
60 | from integration.TLSAsyncDispatcherMixIn import TLSAsyncDispatcherMixIn
61 | from integration.POP3_TLS import POP3_TLS
62 | from integration.IMAP4_TLS import IMAP4_TLS
63 | from integration.SMTP_TLS import SMTP_TLS
64 | from integration.XMLRPCTransport import XMLRPCTransport
65 | try:
66 | import twisted
67 | del(twisted)
68 | from integration.TLSTwistedProtocolWrapper import TLSTwistedProtocolWrapper
69 | except ImportError:
70 | pass
71 |
72 | from utils.cryptomath import cryptlibpyLoaded, m2cryptoLoaded, gmpyLoaded, \
73 | pycryptoLoaded, prngName
74 | from utils.keyfactory import generateRSAKey, parsePEMKey, parseXMLKey, \
75 | parseAsPublicKey, parsePrivateKey
76 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/VerifierDB.py:
--------------------------------------------------------------------------------
1 | """Class for storing SRP password verifiers."""
2 |
3 | from utils.cryptomath import *
4 | from utils.compat import *
5 | import mathtls
6 | from BaseDB import BaseDB
7 |
8 | class VerifierDB(BaseDB):
9 | """This class represent an in-memory or on-disk database of SRP
10 | password verifiers.
11 |
12 | A VerifierDB can be passed to a server handshake to authenticate
13 | a client based on one of the verifiers.
14 |
15 | This class is thread-safe.
16 | """
17 | def __init__(self, filename=None):
18 | """Create a new VerifierDB instance.
19 |
20 | @type filename: str
21 | @param filename: Filename for an on-disk database, or None for
22 | an in-memory database. If the filename already exists, follow
23 | this with a call to open(). To create a new on-disk database,
24 | follow this with a call to create().
25 | """
26 | BaseDB.__init__(self, filename, "verifier")
27 |
28 | def _getItem(self, username, valueStr):
29 | (N, g, salt, verifier) = valueStr.split(" ")
30 | N = base64ToNumber(N)
31 | g = base64ToNumber(g)
32 | salt = base64ToString(salt)
33 | verifier = base64ToNumber(verifier)
34 | return (N, g, salt, verifier)
35 |
36 | def __setitem__(self, username, verifierEntry):
37 | """Add a verifier entry to the database.
38 |
39 | @type username: str
40 | @param username: The username to associate the verifier with.
41 | Must be less than 256 characters in length. Must not already
42 | be in the database.
43 |
44 | @type verifierEntry: tuple
45 | @param verifierEntry: The verifier entry to add. Use
46 | L{tlslite.VerifierDB.VerifierDB.makeVerifier} to create a
47 | verifier entry.
48 | """
49 | BaseDB.__setitem__(self, username, verifierEntry)
50 |
51 |
52 | def _setItem(self, username, value):
53 | if len(username)>=256:
54 | raise ValueError("username too long")
55 | N, g, salt, verifier = value
56 | N = numberToBase64(N)
57 | g = numberToBase64(g)
58 | salt = stringToBase64(salt)
59 | verifier = numberToBase64(verifier)
60 | valueStr = " ".join( (N, g, salt, verifier) )
61 | return valueStr
62 |
63 | def _checkItem(self, value, username, param):
64 | (N, g, salt, verifier) = value
65 | x = mathtls.makeX(salt, username, param)
66 | v = powMod(g, x, N)
67 | return (verifier == v)
68 |
69 |
70 | def makeVerifier(username, password, bits):
71 | """Create a verifier entry which can be stored in a VerifierDB.
72 |
73 | @type username: str
74 | @param username: The username for this verifier. Must be less
75 | than 256 characters in length.
76 |
77 | @type password: str
78 | @param password: The password for this verifier.
79 |
80 | @type bits: int
81 | @param bits: This values specifies which SRP group parameters
82 | to use. It must be one of (1024, 1536, 2048, 3072, 4096, 6144,
83 | 8192). Larger values are more secure but slower. 2048 is a
84 | good compromise between safety and speed.
85 |
86 | @rtype: tuple
87 | @return: A tuple which may be stored in a VerifierDB.
88 | """
89 | return mathtls.makeVerifier(username, password, bits)
90 | makeVerifier = staticmethod(makeVerifier)
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/cipherfactory.py:
--------------------------------------------------------------------------------
1 | """Factory functions for symmetric cryptography."""
2 |
3 | import os
4 |
5 | import Python_AES
6 | import Python_RC4
7 |
8 | import cryptomath
9 |
10 | tripleDESPresent = False
11 |
12 | if cryptomath.m2cryptoLoaded:
13 | import OpenSSL_AES
14 | import OpenSSL_RC4
15 | import OpenSSL_TripleDES
16 | tripleDESPresent = True
17 |
18 | if cryptomath.cryptlibpyLoaded:
19 | import Cryptlib_AES
20 | import Cryptlib_RC4
21 | import Cryptlib_TripleDES
22 | tripleDESPresent = True
23 |
24 | if cryptomath.pycryptoLoaded:
25 | import PyCrypto_AES
26 | import PyCrypto_RC4
27 | import PyCrypto_TripleDES
28 | tripleDESPresent = True
29 |
30 | # **************************************************************************
31 | # Factory Functions for AES
32 | # **************************************************************************
33 |
34 | def createAES(key, IV, implList=None):
35 | """Create a new AES object.
36 |
37 | @type key: str
38 | @param key: A 16, 24, or 32 byte string.
39 |
40 | @type IV: str
41 | @param IV: A 16 byte string
42 |
43 | @rtype: L{tlslite.utils.AES}
44 | @return: An AES object.
45 | """
46 | if implList == None:
47 | implList = ["cryptlib", "openssl", "pycrypto", "python"]
48 |
49 | for impl in implList:
50 | if impl == "cryptlib" and cryptomath.cryptlibpyLoaded:
51 | return Cryptlib_AES.new(key, 2, IV)
52 | elif impl == "openssl" and cryptomath.m2cryptoLoaded:
53 | return OpenSSL_AES.new(key, 2, IV)
54 | elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
55 | return PyCrypto_AES.new(key, 2, IV)
56 | elif impl == "python":
57 | return Python_AES.new(key, 2, IV)
58 | raise NotImplementedError()
59 |
60 | def createRC4(key, IV, implList=None):
61 | """Create a new RC4 object.
62 |
63 | @type key: str
64 | @param key: A 16 to 32 byte string.
65 |
66 | @type IV: object
67 | @param IV: Ignored, whatever it is.
68 |
69 | @rtype: L{tlslite.utils.RC4}
70 | @return: An RC4 object.
71 | """
72 | if implList == None:
73 | implList = ["cryptlib", "openssl", "pycrypto", "python"]
74 |
75 | if len(IV) != 0:
76 | raise AssertionError()
77 | for impl in implList:
78 | if impl == "cryptlib" and cryptomath.cryptlibpyLoaded:
79 | return Cryptlib_RC4.new(key)
80 | elif impl == "openssl" and cryptomath.m2cryptoLoaded:
81 | return OpenSSL_RC4.new(key)
82 | elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
83 | return PyCrypto_RC4.new(key)
84 | elif impl == "python":
85 | return Python_RC4.new(key)
86 | raise NotImplementedError()
87 |
88 | #Create a new TripleDES instance
89 | def createTripleDES(key, IV, implList=None):
90 | """Create a new 3DES object.
91 |
92 | @type key: str
93 | @param key: A 24 byte string.
94 |
95 | @type IV: str
96 | @param IV: An 8 byte string
97 |
98 | @rtype: L{tlslite.utils.TripleDES}
99 | @return: A 3DES object.
100 | """
101 | if implList == None:
102 | implList = ["cryptlib", "openssl", "pycrypto"]
103 |
104 | for impl in implList:
105 | if impl == "cryptlib" and cryptomath.cryptlibpyLoaded:
106 | return Cryptlib_TripleDES.new(key, 2, IV)
107 | elif impl == "openssl" and cryptomath.m2cryptoLoaded:
108 | return OpenSSL_TripleDES.new(key, 2, IV)
109 | elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
110 | return PyCrypto_TripleDES.new(key, 2, IV)
111 | raise NotImplementedError()
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/hmac.py:
--------------------------------------------------------------------------------
1 | """HMAC (Keyed-Hashing for Message Authentication) Python module.
2 |
3 | Implements the HMAC algorithm as described by RFC 2104.
4 |
5 | (This file is modified from the standard library version to do faster
6 | copying)
7 | """
8 |
9 | def _strxor(s1, s2):
10 | """Utility method. XOR the two strings s1 and s2 (must have same length).
11 | """
12 | return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2))
13 |
14 | # The size of the digests returned by HMAC depends on the underlying
15 | # hashing module used.
16 | digest_size = None
17 |
18 | class HMAC:
19 | """RFC2104 HMAC class.
20 |
21 | This supports the API for Cryptographic Hash Functions (PEP 247).
22 | """
23 |
24 | def __init__(self, key, msg = None, digestmod = None):
25 | """Create a new HMAC object.
26 |
27 | key: key for the keyed hash object.
28 | msg: Initial input for the hash, if provided.
29 | digestmod: A module supporting PEP 247. Defaults to the md5 module.
30 | """
31 | if digestmod is None:
32 | import md5
33 | digestmod = md5
34 |
35 | if key == None: #TREVNEW - for faster copying
36 | return #TREVNEW
37 |
38 | self.digestmod = digestmod
39 | self.outer = digestmod.new()
40 | self.inner = digestmod.new()
41 | self.digest_size = digestmod.digest_size
42 |
43 | blocksize = 64
44 | ipad = "\x36" * blocksize
45 | opad = "\x5C" * blocksize
46 |
47 | if len(key) > blocksize:
48 | key = digestmod.new(key).digest()
49 |
50 | key = key + chr(0) * (blocksize - len(key))
51 | self.outer.update(_strxor(key, opad))
52 | self.inner.update(_strxor(key, ipad))
53 | if msg is not None:
54 | self.update(msg)
55 |
56 | ## def clear(self):
57 | ## raise NotImplementedError, "clear() method not available in HMAC."
58 |
59 | def update(self, msg):
60 | """Update this hashing object with the string msg.
61 | """
62 | self.inner.update(msg)
63 |
64 | def copy(self):
65 | """Return a separate copy of this hashing object.
66 |
67 | An update to this copy won't affect the original object.
68 | """
69 | other = HMAC(None) #TREVNEW - for faster copying
70 | other.digest_size = self.digest_size #TREVNEW
71 | other.digestmod = self.digestmod
72 | other.inner = self.inner.copy()
73 | other.outer = self.outer.copy()
74 | return other
75 |
76 | def digest(self):
77 | """Return the hash value of this hashing object.
78 |
79 | This returns a string containing 8-bit data. The object is
80 | not altered in any way by this function; you can continue
81 | updating the object after calling this function.
82 | """
83 | h = self.outer.copy()
84 | h.update(self.inner.digest())
85 | return h.digest()
86 |
87 | def hexdigest(self):
88 | """Like digest(), but returns a string of hexadecimal digits instead.
89 | """
90 | return "".join([hex(ord(x))[2:].zfill(2)
91 | for x in tuple(self.digest())])
92 |
93 | def new(key, msg = None, digestmod = None):
94 | """Create a new hashing object and return it.
95 |
96 | key: The starting key for the hash.
97 | msg: if available, will immediately be hashed into the object's starting
98 | state.
99 |
100 | You can now feed arbitrary strings into the object using its update()
101 | method, and can ask for the hash value at any time by calling its digest()
102 | method.
103 | """
104 | return HMAC(key, msg, digestmod)
105 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/Hash/HMAC.py:
--------------------------------------------------------------------------------
1 | """HMAC (Keyed-Hashing for Message Authentication) Python module.
2 |
3 | Implements the HMAC algorithm as described by RFC 2104.
4 |
5 | This is just a copy of the Python 2.2 HMAC module, modified to work when
6 | used on versions of Python before 2.2.
7 | """
8 |
9 | __revision__ = "$Id: HMAC.py,v 1.5 2002/07/25 17:19:02 z3p Exp $"
10 |
11 | import string
12 |
13 | def _strxor(s1, s2):
14 | """Utility method. XOR the two strings s1 and s2 (must have same length).
15 | """
16 | return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2))
17 |
18 | # The size of the digests returned by HMAC depends on the underlying
19 | # hashing module used.
20 | digest_size = None
21 |
22 | class HMAC:
23 | """RFC2104 HMAC class.
24 |
25 | This supports the API for Cryptographic Hash Functions (PEP 247).
26 | """
27 |
28 | def __init__(self, key, msg = None, digestmod = None):
29 | """Create a new HMAC object.
30 |
31 | key: key for the keyed hash object.
32 | msg: Initial input for the hash, if provided.
33 | digestmod: A module supporting PEP 247. Defaults to the md5 module.
34 | """
35 | if digestmod == None:
36 | import md5
37 | digestmod = md5
38 |
39 | self.digestmod = digestmod
40 | self.outer = digestmod.new()
41 | self.inner = digestmod.new()
42 | try:
43 | self.digest_size = digestmod.digest_size
44 | except AttributeError:
45 | self.digest_size = len(self.outer.digest())
46 |
47 | blocksize = 64
48 | ipad = "\x36" * blocksize
49 | opad = "\x5C" * blocksize
50 |
51 | if len(key) > blocksize:
52 | key = digestmod.new(key).digest()
53 |
54 | key = key + chr(0) * (blocksize - len(key))
55 | self.outer.update(_strxor(key, opad))
56 | self.inner.update(_strxor(key, ipad))
57 | if (msg):
58 | self.update(msg)
59 |
60 | ## def clear(self):
61 | ## raise NotImplementedError, "clear() method not available in HMAC."
62 |
63 | def update(self, msg):
64 | """Update this hashing object with the string msg.
65 | """
66 | self.inner.update(msg)
67 |
68 | def copy(self):
69 | """Return a separate copy of this hashing object.
70 |
71 | An update to this copy won't affect the original object.
72 | """
73 | other = HMAC("")
74 | other.digestmod = self.digestmod
75 | other.inner = self.inner.copy()
76 | other.outer = self.outer.copy()
77 | return other
78 |
79 | def digest(self):
80 | """Return the hash value of this hashing object.
81 |
82 | This returns a string containing 8-bit data. The object is
83 | not altered in any way by this function; you can continue
84 | updating the object after calling this function.
85 | """
86 | h = self.outer.copy()
87 | h.update(self.inner.digest())
88 | return h.digest()
89 |
90 | def hexdigest(self):
91 | """Like digest(), but returns a string of hexadecimal digits instead.
92 | """
93 | return "".join([string.zfill(hex(ord(x))[2:], 2)
94 | for x in tuple(self.digest())])
95 |
96 | def new(key, msg = None, digestmod = None):
97 | """Create a new hashing object and return it.
98 |
99 | key: The starting key for the hash.
100 | msg: if available, will immediately be hashed into the object's starting
101 | state.
102 |
103 | You can now feed arbitrary strings into the object using its update()
104 | method, and can ask for the hash value at any time by calling its digest()
105 | method.
106 | """
107 | return HMAC(key, msg, digestmod)
108 |
109 |
--------------------------------------------------------------------------------
/intercom/gdata/alt/app_engine.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
18 | """Provides functions to persist serialized auth tokens in the datastore.
19 |
20 | The get_token and set_token functions should be used in conjunction with
21 | gdata.gauth's token_from_blob and token_to_blob to allow auth token objects
22 | to be reused across requests. It is up to your own code to ensure that the
23 | token key's are unique.
24 | """
25 |
26 | __author__ = 'j.s@google.com (Jeff Scudder)'
27 |
28 |
29 | from google.appengine.ext import db
30 | from google.appengine.api import memcache
31 |
32 |
33 | class Token(db.Model):
34 | """Datastore Model which stores a serialized auth token."""
35 | t = db.BlobProperty()
36 |
37 |
38 | def get_token(unique_key):
39 | """Searches for a stored token with the desired key.
40 |
41 | Checks memcache and then the datastore if required.
42 |
43 | Args:
44 | unique_key: str which uniquely identifies the desired auth token.
45 |
46 | Returns:
47 | A string encoding the auth token data. Use gdata.gauth.token_from_blob to
48 | convert back into a usable token object. None if the token was not found
49 | in memcache or the datastore.
50 | """
51 | token_string = memcache.get(unique_key)
52 | if token_string is None:
53 | # The token wasn't in memcache, so look in the datastore.
54 | token = Token.get_by_key_name(unique_key)
55 | if token is None:
56 | return None
57 | return token.t
58 | return token_string
59 |
60 |
61 | def set_token(unique_key, token_str):
62 | """Saves the serialized auth token in the datastore.
63 |
64 | The token is also stored in memcache to speed up retrieval on a cache hit.
65 |
66 | Args:
67 | unique_key: The unique name for this token as a string. It is up to your
68 | code to ensure that this token value is unique in your application.
69 | Previous values will be silently overwitten.
70 | token_str: A serialized auth token as a string. I expect that this string
71 | will be generated by gdata.gauth.token_to_blob.
72 |
73 | Returns:
74 | True if the token was stored sucessfully, False if the token could not be
75 | safely cached (if an old value could not be cleared). If the token was
76 | set in memcache, but not in the datastore, this function will return None.
77 | However, in that situation an exception will likely be raised.
78 |
79 | Raises:
80 | Datastore exceptions may be raised from the App Engine SDK in the event of
81 | failure.
82 | """
83 | # First try to save in memcache.
84 | result = memcache.set(unique_key, token_str)
85 | # If memcache fails to save the value, clear the cached value.
86 | if not result:
87 | result = memcache.delete(unique_key)
88 | # If we could not clear the cached value for this token, refuse to save.
89 | if result == 0:
90 | return False
91 | # Save to the datastore.
92 | if Token(key_name=unique_key, t=token_str).put():
93 | return True
94 | return None
95 |
96 |
97 | def delete_token(unique_key):
98 | # Clear from memcache.
99 | memcache.delete(unique_key)
100 | # Clear from the datastore.
101 | Token(key_name=unique_key).delete()
102 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/SessionCache.py:
--------------------------------------------------------------------------------
1 | """Class for caching TLS sessions."""
2 |
3 | import thread
4 | import time
5 |
6 | class SessionCache:
7 | """This class is used by the server to cache TLS sessions.
8 |
9 | Caching sessions allows the client to use TLS session resumption
10 | and avoid the expense of a full handshake. To use this class,
11 | simply pass a SessionCache instance into the server handshake
12 | function.
13 |
14 | This class is thread-safe.
15 | """
16 |
17 | #References to these instances
18 | #are also held by the caller, who may change the 'resumable'
19 | #flag, so the SessionCache must return the same instances
20 | #it was passed in.
21 |
22 | def __init__(self, maxEntries=10000, maxAge=14400):
23 | """Create a new SessionCache.
24 |
25 | @type maxEntries: int
26 | @param maxEntries: The maximum size of the cache. When this
27 | limit is reached, the oldest sessions will be deleted as
28 | necessary to make room for new ones. The default is 10000.
29 |
30 | @type maxAge: int
31 | @param maxAge: The number of seconds before a session expires
32 | from the cache. The default is 14400 (i.e. 4 hours)."""
33 |
34 | self.lock = thread.allocate_lock()
35 |
36 | # Maps sessionIDs to sessions
37 | self.entriesDict = {}
38 |
39 | #Circular list of (sessionID, timestamp) pairs
40 | self.entriesList = [(None,None)] * maxEntries
41 |
42 | self.firstIndex = 0
43 | self.lastIndex = 0
44 | self.maxAge = maxAge
45 |
46 | def __getitem__(self, sessionID):
47 | self.lock.acquire()
48 | try:
49 | self._purge() #Delete old items, so we're assured of a new one
50 | session = self.entriesDict[sessionID]
51 |
52 | #When we add sessions they're resumable, but it's possible
53 | #for the session to be invalidated later on (if a fatal alert
54 | #is returned), so we have to check for resumability before
55 | #returning the session.
56 |
57 | if session.valid():
58 | return session
59 | else:
60 | raise KeyError()
61 | finally:
62 | self.lock.release()
63 |
64 |
65 | def __setitem__(self, sessionID, session):
66 | self.lock.acquire()
67 | try:
68 | #Add the new element
69 | self.entriesDict[sessionID] = session
70 | self.entriesList[self.lastIndex] = (sessionID, time.time())
71 | self.lastIndex = (self.lastIndex+1) % len(self.entriesList)
72 |
73 | #If the cache is full, we delete the oldest element to make an
74 | #empty space
75 | if self.lastIndex == self.firstIndex:
76 | del(self.entriesDict[self.entriesList[self.firstIndex][0]])
77 | self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
78 | finally:
79 | self.lock.release()
80 |
81 | #Delete expired items
82 | def _purge(self):
83 | currentTime = time.time()
84 |
85 | #Search through the circular list, deleting expired elements until
86 | #we reach a non-expired element. Since elements in list are
87 | #ordered in time, we can break once we reach the first non-expired
88 | #element
89 | index = self.firstIndex
90 | while index != self.lastIndex:
91 | if currentTime - self.entriesList[index][1] > self.maxAge:
92 | del(self.entriesDict[self.entriesList[index][0]])
93 | index = (index+1) % len(self.entriesList)
94 | else:
95 | break
96 | self.firstIndex = index
97 |
98 | def _test():
99 | import doctest, SessionCache
100 | return doctest.testmod(SessionCache)
101 |
102 | if __name__ == "__main__":
103 | _test()
104 |
--------------------------------------------------------------------------------
/intercom/gdata/projecthosting/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright 2009 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 |
18 | # This module is used for version 2 of the Google Data APIs.
19 |
20 |
21 | """Provides classes and constants for XML in the Google Project Hosting API.
22 |
23 | Canonical documentation for the raw XML which these classes represent can be
24 | found here: http://code.google.com/p/support/wiki/IssueTrackerAPI
25 | """
26 |
27 |
28 | __author__ = 'jlapenna@google.com (Joe LaPenna)'
29 |
30 | import atom.core
31 | import gdata.data
32 |
33 |
34 | ISSUES_TEMPLATE = '{http://schemas.google.com/projecthosting/issues/2009}%s'
35 |
36 |
37 | ISSUES_FULL_FEED = '/feeds/issues/p/%s/issues/full'
38 | COMMENTS_FULL_FEED = '/feeds/issues/p/%s/issues/%s/comments/full'
39 |
40 |
41 | class Uri(atom.core.XmlElement):
42 | """The issues:uri element."""
43 | _qname = ISSUES_TEMPLATE % 'uri'
44 |
45 |
46 | class Username(atom.core.XmlElement):
47 | """The issues:username element."""
48 | _qname = ISSUES_TEMPLATE % 'username'
49 |
50 |
51 | class Cc(atom.core.XmlElement):
52 | """The issues:cc element."""
53 | _qname = ISSUES_TEMPLATE % 'cc'
54 | uri = Uri
55 | username = Username
56 |
57 |
58 | class Label(atom.core.XmlElement):
59 | """The issues:label element."""
60 | _qname = ISSUES_TEMPLATE % 'label'
61 |
62 |
63 | class Owner(atom.core.XmlElement):
64 | """The issues:owner element."""
65 | _qname = ISSUES_TEMPLATE % 'owner'
66 | uri = Uri
67 | username = Username
68 |
69 |
70 | class Stars(atom.core.XmlElement):
71 | """The issues:stars element."""
72 | _qname = ISSUES_TEMPLATE % 'stars'
73 |
74 |
75 | class State(atom.core.XmlElement):
76 | """The issues:state element."""
77 | _qname = ISSUES_TEMPLATE % 'state'
78 |
79 |
80 | class Status(atom.core.XmlElement):
81 | """The issues:status element."""
82 | _qname = ISSUES_TEMPLATE % 'status'
83 |
84 |
85 | class Summary(atom.core.XmlElement):
86 | """The issues:summary element."""
87 | _qname = ISSUES_TEMPLATE % 'summary'
88 |
89 |
90 | class OwnerUpdate(atom.core.XmlElement):
91 | """The issues:ownerUpdate element."""
92 | _qname = ISSUES_TEMPLATE % 'ownerUpdate'
93 |
94 |
95 | class CcUpdate(atom.core.XmlElement):
96 | """The issues:ccUpdate element."""
97 | _qname = ISSUES_TEMPLATE % 'ccUpdate'
98 |
99 |
100 | class Updates(atom.core.XmlElement):
101 | """The issues:updates element."""
102 | _qname = ISSUES_TEMPLATE % 'updates'
103 | summary = Summary
104 | status = Status
105 | ownerUpdate = OwnerUpdate
106 | label = [Label]
107 | ccUpdate = [CcUpdate]
108 |
109 |
110 | class IssueEntry(gdata.data.GDEntry):
111 | """Represents the information of one issue."""
112 | _qname = atom.data.ATOM_TEMPLATE % 'entry'
113 | owner = Owner
114 | cc = [Cc]
115 | label = [Label]
116 | stars = Stars
117 | state = State
118 | status = Status
119 |
120 |
121 | class IssuesFeed(gdata.data.GDFeed):
122 | """An Atom feed listing a project's issues."""
123 | entry = [IssueEntry]
124 |
125 |
126 | class CommentEntry(gdata.data.GDEntry):
127 | """An entry detailing one comment on an issue."""
128 | _qname = atom.data.ATOM_TEMPLATE % 'entry'
129 | updates = Updates
130 |
131 |
132 | class CommentsFeed(gdata.data.GDFeed):
133 | """An Atom feed listing a project's issue's comments."""
134 | entry = [CommentEntry]
135 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/BaseDB.py:
--------------------------------------------------------------------------------
1 | """Base class for SharedKeyDB and VerifierDB."""
2 |
3 | import anydbm
4 | import thread
5 |
6 | class BaseDB:
7 | def __init__(self, filename, type):
8 | self.type = type
9 | self.filename = filename
10 | if self.filename:
11 | self.db = None
12 | else:
13 | self.db = {}
14 | self.lock = thread.allocate_lock()
15 |
16 | def create(self):
17 | """Create a new on-disk database.
18 |
19 | @raise anydbm.error: If there's a problem creating the database.
20 | """
21 | if self.filename:
22 | self.db = anydbm.open(self.filename, "n") #raises anydbm.error
23 | self.db["--Reserved--type"] = self.type
24 | self.db.sync()
25 | else:
26 | self.db = {}
27 |
28 | def open(self):
29 | """Open a pre-existing on-disk database.
30 |
31 | @raise anydbm.error: If there's a problem opening the database.
32 | @raise ValueError: If the database is not of the right type.
33 | """
34 | if not self.filename:
35 | raise ValueError("Can only open on-disk databases")
36 | self.db = anydbm.open(self.filename, "w") #raises anydbm.error
37 | try:
38 | if self.db["--Reserved--type"] != self.type:
39 | raise ValueError("Not a %s database" % self.type)
40 | except KeyError:
41 | raise ValueError("Not a recognized database")
42 |
43 | def __getitem__(self, username):
44 | if self.db == None:
45 | raise AssertionError("DB not open")
46 |
47 | self.lock.acquire()
48 | try:
49 | valueStr = self.db[username]
50 | finally:
51 | self.lock.release()
52 |
53 | return self._getItem(username, valueStr)
54 |
55 | def __setitem__(self, username, value):
56 | if self.db == None:
57 | raise AssertionError("DB not open")
58 |
59 | valueStr = self._setItem(username, value)
60 |
61 | self.lock.acquire()
62 | try:
63 | self.db[username] = valueStr
64 | if self.filename:
65 | self.db.sync()
66 | finally:
67 | self.lock.release()
68 |
69 | def __delitem__(self, username):
70 | if self.db == None:
71 | raise AssertionError("DB not open")
72 |
73 | self.lock.acquire()
74 | try:
75 | del(self.db[username])
76 | if self.filename:
77 | self.db.sync()
78 | finally:
79 | self.lock.release()
80 |
81 | def __contains__(self, username):
82 | """Check if the database contains the specified username.
83 |
84 | @type username: str
85 | @param username: The username to check for.
86 |
87 | @rtype: bool
88 | @return: True if the database contains the username, False
89 | otherwise.
90 |
91 | """
92 | if self.db == None:
93 | raise AssertionError("DB not open")
94 |
95 | self.lock.acquire()
96 | try:
97 | return self.db.has_key(username)
98 | finally:
99 | self.lock.release()
100 |
101 | def check(self, username, param):
102 | value = self.__getitem__(username)
103 | return self._checkItem(value, username, param)
104 |
105 | def keys(self):
106 | """Return a list of usernames in the database.
107 |
108 | @rtype: list
109 | @return: The usernames in the database.
110 | """
111 | if self.db == None:
112 | raise AssertionError("DB not open")
113 |
114 | self.lock.acquire()
115 | try:
116 | usernames = self.db.keys()
117 | finally:
118 | self.lock.release()
119 | usernames = [u for u in usernames if not u.startswith("--Reserved--")]
120 | return usernames
--------------------------------------------------------------------------------
/intercom/twilio/contrib/httplib2/iri2uri.py:
--------------------------------------------------------------------------------
1 | """
2 | iri2uri
3 |
4 | Converts an IRI to a URI.
5 |
6 | """
7 | __author__ = "Joe Gregorio (joe@bitworking.org)"
8 | __copyright__ = "Copyright 2006, Joe Gregorio"
9 | __contributors__ = []
10 | __version__ = "1.0.0"
11 | __license__ = "MIT"
12 | __history__ = """
13 | """
14 |
15 | import urlparse
16 |
17 |
18 | # Convert an IRI to a URI following the rules in RFC 3987
19 | #
20 | # The characters we need to enocde and escape are defined in the spec:
21 | #
22 | # iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
23 | # ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
24 | # / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
25 | # / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
26 | # / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
27 | # / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
28 | # / %xD0000-DFFFD / %xE1000-EFFFD
29 |
30 | escape_range = [
31 | (0xA0, 0xD7FF ),
32 | (0xE000, 0xF8FF ),
33 | (0xF900, 0xFDCF ),
34 | (0xFDF0, 0xFFEF),
35 | (0x10000, 0x1FFFD ),
36 | (0x20000, 0x2FFFD ),
37 | (0x30000, 0x3FFFD),
38 | (0x40000, 0x4FFFD ),
39 | (0x50000, 0x5FFFD ),
40 | (0x60000, 0x6FFFD),
41 | (0x70000, 0x7FFFD ),
42 | (0x80000, 0x8FFFD ),
43 | (0x90000, 0x9FFFD),
44 | (0xA0000, 0xAFFFD ),
45 | (0xB0000, 0xBFFFD ),
46 | (0xC0000, 0xCFFFD),
47 | (0xD0000, 0xDFFFD ),
48 | (0xE1000, 0xEFFFD),
49 | (0xF0000, 0xFFFFD ),
50 | (0x100000, 0x10FFFD)
51 | ]
52 |
53 | def encode(c):
54 | retval = c
55 | i = ord(c)
56 | for low, high in escape_range:
57 | if i < low:
58 | break
59 | if i >= low and i <= high:
60 | retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')])
61 | break
62 | return retval
63 |
64 |
65 | def iri2uri(uri):
66 | """Convert an IRI to a URI. Note that IRIs must be
67 | passed in a unicode strings. That is, do not utf-8 encode
68 | the IRI before passing it into the function."""
69 | if isinstance(uri ,unicode):
70 | (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri)
71 | authority = authority.encode('idna')
72 | # For each character in 'ucschar' or 'iprivate'
73 | # 1. encode as utf-8
74 | # 2. then %-encode each octet of that utf-8
75 | uri = urlparse.urlunsplit((scheme, authority, path, query, fragment))
76 | uri = "".join([encode(c) for c in uri])
77 | return uri
78 |
79 | if __name__ == "__main__":
80 | import unittest
81 |
82 | class Test(unittest.TestCase):
83 |
84 | def test_uris(self):
85 | """Test that URIs are invariant under the transformation."""
86 | invariant = [
87 | u"ftp://ftp.is.co.za/rfc/rfc1808.txt",
88 | u"http://www.ietf.org/rfc/rfc2396.txt",
89 | u"ldap://[2001:db8::7]/c=GB?objectClass?one",
90 | u"mailto:John.Doe@example.com",
91 | u"news:comp.infosystems.www.servers.unix",
92 | u"tel:+1-816-555-1212",
93 | u"telnet://192.0.2.16:80/",
94 | u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ]
95 | for uri in invariant:
96 | self.assertEqual(uri, iri2uri(uri))
97 |
98 | def test_iri(self):
99 | """ Test that the right type of escaping is done for each part of the URI."""
100 | self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}"))
101 | self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}"))
102 | self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}"))
103 | self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}"))
104 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))
105 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")))
106 | self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8')))
107 |
108 | unittest.main()
109 |
110 |
111 |
--------------------------------------------------------------------------------
/intercom/atom/token_store.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 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 | """This module provides a TokenStore class which is designed to manage
18 | auth tokens required for different services.
19 |
20 | Each token is valid for a set of scopes which is the start of a URL. An HTTP
21 | client will use a token store to find a valid Authorization header to send
22 | in requests to the specified URL. If the HTTP client determines that a token
23 | has expired or been revoked, it can remove the token from the store so that
24 | it will not be used in future requests.
25 | """
26 |
27 |
28 | __author__ = 'api.jscudder (Jeff Scudder)'
29 |
30 |
31 | import atom.http_interface
32 | import atom.url
33 |
34 |
35 | SCOPE_ALL = 'http'
36 |
37 |
38 | class TokenStore(object):
39 | """Manages Authorization tokens which will be sent in HTTP headers."""
40 | def __init__(self, scoped_tokens=None):
41 | self._tokens = scoped_tokens or {}
42 |
43 | def add_token(self, token):
44 | """Adds a new token to the store (replaces tokens with the same scope).
45 |
46 | Args:
47 | token: A subclass of http_interface.GenericToken. The token object is
48 | responsible for adding the Authorization header to the HTTP request.
49 | The scopes defined in the token are used to determine if the token
50 | is valid for a requested scope when find_token is called.
51 |
52 | Returns:
53 | True if the token was added, False if the token was not added becase
54 | no scopes were provided.
55 | """
56 | if not hasattr(token, 'scopes') or not token.scopes:
57 | return False
58 |
59 | for scope in token.scopes:
60 | self._tokens[str(scope)] = token
61 | return True
62 |
63 | def find_token(self, url):
64 | """Selects an Authorization header token which can be used for the URL.
65 |
66 | Args:
67 | url: str or atom.url.Url or a list containing the same.
68 | The URL which is going to be requested. All
69 | tokens are examined to see if any scopes begin match the beginning
70 | of the URL. The first match found is returned.
71 |
72 | Returns:
73 | The token object which should execute the HTTP request. If there was
74 | no token for the url (the url did not begin with any of the token
75 | scopes available), then the atom.http_interface.GenericToken will be
76 | returned because the GenericToken calls through to the http client
77 | without adding an Authorization header.
78 | """
79 | if url is None:
80 | return None
81 | if isinstance(url, (str, unicode)):
82 | url = atom.url.parse_url(url)
83 | if url in self._tokens:
84 | token = self._tokens[url]
85 | if token.valid_for_scope(url):
86 | return token
87 | else:
88 | del self._tokens[url]
89 | for scope, token in self._tokens.iteritems():
90 | if token.valid_for_scope(url):
91 | return token
92 | return atom.http_interface.GenericToken()
93 |
94 | def remove_token(self, token):
95 | """Removes the token from the token_store.
96 |
97 | This method is used when a token is determined to be invalid. If the
98 | token was found by find_token, but resulted in a 401 or 403 error stating
99 | that the token was invlid, then the token should be removed to prevent
100 | future use.
101 |
102 | Returns:
103 | True if a token was found and then removed from the token
104 | store. False if the token was not in the TokenStore.
105 | """
106 | token_found = False
107 | scopes_to_delete = []
108 | for scope, stored_token in self._tokens.iteritems():
109 | if stored_token == token:
110 | scopes_to_delete.append(scope)
111 | token_found = True
112 | for scope in scopes_to_delete:
113 | del self._tokens[scope]
114 | return token_found
115 |
116 | def remove_all_tokens(self):
117 | self._tokens = {}
118 |
--------------------------------------------------------------------------------
/intercom/gdata/Crypto/PublicKey/ElGamal.py:
--------------------------------------------------------------------------------
1 | #
2 | # ElGamal.py : ElGamal encryption/decryption and signatures
3 | #
4 | # Part of the Python Cryptography Toolkit
5 | #
6 | # Distribute and use freely; there are no restrictions on further
7 | # dissemination and usage except those imposed by the laws of your
8 | # country of residence. This software is provided "as is" without
9 | # warranty of fitness for use or suitability for any purpose, express
10 | # or implied. Use at your own risk or not at all.
11 | #
12 |
13 | __revision__ = "$Id: ElGamal.py,v 1.9 2003/04/04 19:44:26 akuchling Exp $"
14 |
15 | from Crypto.PublicKey.pubkey import *
16 | from Crypto.Util import number
17 |
18 | class error (Exception):
19 | pass
20 |
21 | # Generate an ElGamal key with N bits
22 | def generate(bits, randfunc, progress_func=None):
23 | """generate(bits:int, randfunc:callable, progress_func:callable)
24 |
25 | Generate an ElGamal key of length 'bits', using 'randfunc' to get
26 | random data and 'progress_func', if present, to display
27 | the progress of the key generation.
28 | """
29 | obj=ElGamalobj()
30 | # Generate prime p
31 | if progress_func:
32 | progress_func('p\n')
33 | obj.p=bignum(getPrime(bits, randfunc))
34 | # Generate random number g
35 | if progress_func:
36 | progress_func('g\n')
37 | size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p
38 | if size<1:
39 | size=bits-1
40 | while (1):
41 | obj.g=bignum(getPrime(size, randfunc))
42 | if obj.g < obj.p:
43 | break
44 | size=(size+1) % bits
45 | if size==0:
46 | size=4
47 | # Generate random number x
48 | if progress_func:
49 | progress_func('x\n')
50 | while (1):
51 | size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p
52 | if size>2:
53 | break
54 | while (1):
55 | obj.x=bignum(getPrime(size, randfunc))
56 | if obj.x < obj.p:
57 | break
58 | size = (size+1) % bits
59 | if size==0:
60 | size=4
61 | if progress_func:
62 | progress_func('y\n')
63 | obj.y = pow(obj.g, obj.x, obj.p)
64 | return obj
65 |
66 | def construct(tuple):
67 | """construct(tuple:(long,long,long,long)|(long,long,long,long,long)))
68 | : ElGamalobj
69 | Construct an ElGamal key from a 3- or 4-tuple of numbers.
70 | """
71 |
72 | obj=ElGamalobj()
73 | if len(tuple) not in [3,4]:
74 | raise error, 'argument for construct() wrong length'
75 | for i in range(len(tuple)):
76 | field = obj.keydata[i]
77 | setattr(obj, field, tuple[i])
78 | return obj
79 |
80 | class ElGamalobj(pubkey):
81 | keydata=['p', 'g', 'y', 'x']
82 |
83 | def _encrypt(self, M, K):
84 | a=pow(self.g, K, self.p)
85 | b=( M*pow(self.y, K, self.p) ) % self.p
86 | return ( a,b )
87 |
88 | def _decrypt(self, M):
89 | if (not hasattr(self, 'x')):
90 | raise error, 'Private key not available in this object'
91 | ax=pow(M[0], self.x, self.p)
92 | plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
93 | return plaintext
94 |
95 | def _sign(self, M, K):
96 | if (not hasattr(self, 'x')):
97 | raise error, 'Private key not available in this object'
98 | p1=self.p-1
99 | if (GCD(K, p1)!=1):
100 | raise error, 'Bad K value: GCD(K,p-1)!=1'
101 | a=pow(self.g, K, self.p)
102 | t=(M-self.x*a) % p1
103 | while t<0: t=t+p1
104 | b=(t*inverse(K, p1)) % p1
105 | return (a, b)
106 |
107 | def _verify(self, M, sig):
108 | v1=pow(self.y, sig[0], self.p)
109 | v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
110 | v2=pow(self.g, M, self.p)
111 | if v1==v2:
112 | return 1
113 | return 0
114 |
115 | def size(self):
116 | "Return the maximum number of bits that can be handled by this key."
117 | return number.size(self.p) - 1
118 |
119 | def has_private(self):
120 | """Return a Boolean denoting whether the object contains
121 | private components."""
122 | if hasattr(self, 'x'):
123 | return 1
124 | else:
125 | return 0
126 |
127 | def publickey(self):
128 | """Return a new key object containing only the public information."""
129 | return construct((self.p, self.g, self.y))
130 |
131 |
132 | object=ElGamalobj
133 |
--------------------------------------------------------------------------------
/intercom/gdata/media/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 | """Contains the data classes of the Yahoo! Media RSS Extension"""
18 |
19 |
20 | __author__ = 'j.s@google.com (Jeff Scudder)'
21 |
22 |
23 | import atom.core
24 |
25 |
26 | MEDIA_TEMPLATE = '{http://search.yahoo.com/mrss//}%s'
27 |
28 |
29 | class MediaCategory(atom.core.XmlElement):
30 | """Describes a media category."""
31 | _qname = MEDIA_TEMPLATE % 'category'
32 | scheme = 'scheme'
33 | label = 'label'
34 |
35 |
36 | class MediaCopyright(atom.core.XmlElement):
37 | """Describes a media copyright."""
38 | _qname = MEDIA_TEMPLATE % 'copyright'
39 | url = 'url'
40 |
41 |
42 | class MediaCredit(atom.core.XmlElement):
43 | """Describes a media credit."""
44 | _qname = MEDIA_TEMPLATE % 'credit'
45 | role = 'role'
46 | scheme = 'scheme'
47 |
48 |
49 | class MediaDescription(atom.core.XmlElement):
50 | """Describes a media description."""
51 | _qname = MEDIA_TEMPLATE % 'description'
52 | type = 'type'
53 |
54 |
55 | class MediaHash(atom.core.XmlElement):
56 | """Describes a media hash."""
57 | _qname = MEDIA_TEMPLATE % 'hash'
58 | algo = 'algo'
59 |
60 |
61 | class MediaKeywords(atom.core.XmlElement):
62 | """Describes a media keywords."""
63 | _qname = MEDIA_TEMPLATE % 'keywords'
64 |
65 |
66 | class MediaPlayer(atom.core.XmlElement):
67 | """Describes a media player."""
68 | _qname = MEDIA_TEMPLATE % 'player'
69 | height = 'height'
70 | width = 'width'
71 | url = 'url'
72 |
73 |
74 | class MediaRating(atom.core.XmlElement):
75 | """Describes a media rating."""
76 | _qname = MEDIA_TEMPLATE % 'rating'
77 | scheme = 'scheme'
78 |
79 |
80 | class MediaRestriction(atom.core.XmlElement):
81 | """Describes a media restriction."""
82 | _qname = MEDIA_TEMPLATE % 'restriction'
83 | relationship = 'relationship'
84 | type = 'type'
85 |
86 |
87 | class MediaText(atom.core.XmlElement):
88 | """Describes a media text."""
89 | _qname = MEDIA_TEMPLATE % 'text'
90 | end = 'end'
91 | lang = 'lang'
92 | type = 'type'
93 | start = 'start'
94 |
95 |
96 | class MediaThumbnail(atom.core.XmlElement):
97 | """Describes a media thumbnail."""
98 | _qname = MEDIA_TEMPLATE % 'thumbnail'
99 | time = 'time'
100 | url = 'url'
101 | width = 'width'
102 | height = 'height'
103 |
104 |
105 | class MediaTitle(atom.core.XmlElement):
106 | """Describes a media title."""
107 | _qname = MEDIA_TEMPLATE % 'title'
108 | type = 'type'
109 |
110 |
111 | class MediaContent(atom.core.XmlElement):
112 | """Describes a media content."""
113 | _qname = MEDIA_TEMPLATE % 'content'
114 | bitrate = 'bitrate'
115 | is_default = 'isDefault'
116 | medium = 'medium'
117 | height = 'height'
118 | credit = [MediaCredit]
119 | language = 'language'
120 | hash = MediaHash
121 | width = 'width'
122 | player = MediaPlayer
123 | url = 'url'
124 | file_size = 'fileSize'
125 | channels = 'channels'
126 | expression = 'expression'
127 | text = [MediaText]
128 | samplingrate = 'samplingrate'
129 | title = MediaTitle
130 | category = [MediaCategory]
131 | rating = [MediaRating]
132 | type = 'type'
133 | description = MediaDescription
134 | framerate = 'framerate'
135 | thumbnail = [MediaThumbnail]
136 | duration = 'duration'
137 | copyright = MediaCopyright
138 | keywords = MediaKeywords
139 | restriction = [MediaRestriction]
140 |
141 |
142 | class MediaGroup(atom.core.XmlElement):
143 | """Describes a media group."""
144 | _qname = MEDIA_TEMPLATE % 'group'
145 | credit = [MediaCredit]
146 | content = [MediaContent]
147 | copyright = MediaCopyright
148 | description = MediaDescription
149 | category = [MediaCategory]
150 | player = MediaPlayer
151 | rating = [MediaRating]
152 | hash = MediaHash
153 | title = MediaTitle
154 | keywords = MediaKeywords
155 | restriction = [MediaRestriction]
156 | thumbnail = [MediaThumbnail]
157 | text = [MediaText]
158 |
159 |
160 |
--------------------------------------------------------------------------------
/intercom/gdata/finance/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2009 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 |
18 | """Contains the data classes of the Google Finance Portfolio Data API"""
19 |
20 |
21 | __author__ = 'j.s@google.com (Jeff Scudder)'
22 |
23 |
24 | import atom.core
25 | import atom.data
26 | import gdata.data
27 | import gdata.opensearch.data
28 |
29 |
30 | GF_TEMPLATE = '{http://schemas.google.com/finance/2007/}%s'
31 |
32 |
33 | class Commission(atom.core.XmlElement):
34 | """Commission for the transaction"""
35 | _qname = GF_TEMPLATE % 'commission'
36 | money = [gdata.data.Money]
37 |
38 |
39 | class CostBasis(atom.core.XmlElement):
40 | """Cost basis for the portfolio or position"""
41 | _qname = GF_TEMPLATE % 'costBasis'
42 | money = [gdata.data.Money]
43 |
44 |
45 | class DaysGain(atom.core.XmlElement):
46 | """Today's gain for the portfolio or position"""
47 | _qname = GF_TEMPLATE % 'daysGain'
48 | money = [gdata.data.Money]
49 |
50 |
51 | class Gain(atom.core.XmlElement):
52 | """Total gain for the portfolio or position"""
53 | _qname = GF_TEMPLATE % 'gain'
54 | money = [gdata.data.Money]
55 |
56 |
57 | class MarketValue(atom.core.XmlElement):
58 | """Market value for the portfolio or position"""
59 | _qname = GF_TEMPLATE % 'marketValue'
60 | money = [gdata.data.Money]
61 |
62 |
63 | class PortfolioData(atom.core.XmlElement):
64 | """Data for the portfolio"""
65 | _qname = GF_TEMPLATE % 'portfolioData'
66 | return_overall = 'returnOverall'
67 | currency_code = 'currencyCode'
68 | return3y = 'return3y'
69 | return4w = 'return4w'
70 | market_value = MarketValue
71 | return_y_t_d = 'returnYTD'
72 | cost_basis = CostBasis
73 | gain_percentage = 'gainPercentage'
74 | days_gain = DaysGain
75 | return3m = 'return3m'
76 | return5y = 'return5y'
77 | return1w = 'return1w'
78 | gain = Gain
79 | return1y = 'return1y'
80 |
81 |
82 | class PortfolioEntry(gdata.data.GDEntry):
83 | """Describes an entry in a feed of Finance portfolios"""
84 | portfolio_data = PortfolioData
85 |
86 |
87 | class PortfolioFeed(gdata.data.GDFeed):
88 | """Describes a Finance portfolio feed"""
89 | entry = [PortfolioEntry]
90 |
91 |
92 | class PositionData(atom.core.XmlElement):
93 | """Data for the position"""
94 | _qname = GF_TEMPLATE % 'positionData'
95 | return_y_t_d = 'returnYTD'
96 | return5y = 'return5y'
97 | return_overall = 'returnOverall'
98 | cost_basis = CostBasis
99 | return3y = 'return3y'
100 | return1y = 'return1y'
101 | return4w = 'return4w'
102 | shares = 'shares'
103 | days_gain = DaysGain
104 | gain_percentage = 'gainPercentage'
105 | market_value = MarketValue
106 | gain = Gain
107 | return3m = 'return3m'
108 | return1w = 'return1w'
109 |
110 |
111 | class Price(atom.core.XmlElement):
112 | """Price of the transaction"""
113 | _qname = GF_TEMPLATE % 'price'
114 | money = [gdata.data.Money]
115 |
116 |
117 | class Symbol(atom.core.XmlElement):
118 | """Stock symbol for the company"""
119 | _qname = GF_TEMPLATE % 'symbol'
120 | symbol = 'symbol'
121 | exchange = 'exchange'
122 | full_name = 'fullName'
123 |
124 |
125 | class PositionEntry(gdata.data.GDEntry):
126 | """Describes an entry in a feed of Finance positions"""
127 | symbol = Symbol
128 | position_data = PositionData
129 |
130 |
131 | class PositionFeed(gdata.data.GDFeed):
132 | """Describes a Finance position feed"""
133 | entry = [PositionEntry]
134 |
135 |
136 | class TransactionData(atom.core.XmlElement):
137 | """Data for the transction"""
138 | _qname = GF_TEMPLATE % 'transactionData'
139 | shares = 'shares'
140 | notes = 'notes'
141 | date = 'date'
142 | type = 'type'
143 | commission = Commission
144 | price = Price
145 |
146 |
147 | class TransactionEntry(gdata.data.GDEntry):
148 | """Describes an entry in a feed of Finance transactions"""
149 | transaction_data = TransactionData
150 |
151 |
152 | class TransactionFeed(gdata.data.GDFeed):
153 | """Describes a Finance transaction feed"""
154 | entry = [TransactionEntry]
155 |
156 |
157 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/utils/compat.py:
--------------------------------------------------------------------------------
1 | """Miscellaneous functions to mask Python version differences."""
2 |
3 | import sys
4 | import os
5 |
6 | if sys.version_info < (2,2):
7 | raise AssertionError("Python 2.2 or later required")
8 |
9 | if sys.version_info < (2,3):
10 |
11 | def enumerate(collection):
12 | return zip(range(len(collection)), collection)
13 |
14 | class Set:
15 | def __init__(self, seq=None):
16 | self.values = {}
17 | if seq:
18 | for e in seq:
19 | self.values[e] = None
20 |
21 | def add(self, e):
22 | self.values[e] = None
23 |
24 | def discard(self, e):
25 | if e in self.values.keys():
26 | del(self.values[e])
27 |
28 | def union(self, s):
29 | ret = Set()
30 | for e in self.values.keys():
31 | ret.values[e] = None
32 | for e in s.values.keys():
33 | ret.values[e] = None
34 | return ret
35 |
36 | def issubset(self, other):
37 | for e in self.values.keys():
38 | if e not in other.values.keys():
39 | return False
40 | return True
41 |
42 | def __nonzero__( self):
43 | return len(self.values.keys())
44 |
45 | def __contains__(self, e):
46 | return e in self.values.keys()
47 |
48 | def __iter__(self):
49 | return iter(set.values.keys())
50 |
51 |
52 | if os.name != "java":
53 |
54 | import array
55 | def createByteArraySequence(seq):
56 | return array.array('B', seq)
57 | def createByteArrayZeros(howMany):
58 | return array.array('B', [0] * howMany)
59 | def concatArrays(a1, a2):
60 | return a1+a2
61 |
62 | def bytesToString(bytes):
63 | return bytes.tostring()
64 | def stringToBytes(s):
65 | bytes = createByteArrayZeros(0)
66 | bytes.fromstring(s)
67 | return bytes
68 |
69 | import math
70 | def numBits(n):
71 | if n==0:
72 | return 0
73 | s = "%x" % n
74 | return ((len(s)-1)*4) + \
75 | {'0':0, '1':1, '2':2, '3':2,
76 | '4':3, '5':3, '6':3, '7':3,
77 | '8':4, '9':4, 'a':4, 'b':4,
78 | 'c':4, 'd':4, 'e':4, 'f':4,
79 | }[s[0]]
80 | return int(math.floor(math.log(n, 2))+1)
81 |
82 | BaseException = Exception
83 | import sys
84 | import traceback
85 | def formatExceptionTrace(e):
86 | newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
87 | return newStr
88 |
89 | else:
90 | #Jython 2.1 is missing lots of python 2.3 stuff,
91 | #which we have to emulate here:
92 | #NOTE: JYTHON SUPPORT NO LONGER WORKS, DUE TO USE OF GENERATORS.
93 | #THIS CODE IS LEFT IN SO THAT ONE JYTHON UPDATES TO 2.2, IT HAS A
94 | #CHANCE OF WORKING AGAIN.
95 |
96 | import java
97 | import jarray
98 |
99 | def createByteArraySequence(seq):
100 | if isinstance(seq, type("")): #If it's a string, convert
101 | seq = [ord(c) for c in seq]
102 | return jarray.array(seq, 'h') #use short instead of bytes, cause bytes are signed
103 | def createByteArrayZeros(howMany):
104 | return jarray.zeros(howMany, 'h') #use short instead of bytes, cause bytes are signed
105 | def concatArrays(a1, a2):
106 | l = list(a1)+list(a2)
107 | return createByteArraySequence(l)
108 |
109 | #WAY TOO SLOW - MUST BE REPLACED------------
110 | def bytesToString(bytes):
111 | return "".join([chr(b) for b in bytes])
112 |
113 | def stringToBytes(s):
114 | bytes = createByteArrayZeros(len(s))
115 | for count, c in enumerate(s):
116 | bytes[count] = ord(c)
117 | return bytes
118 | #WAY TOO SLOW - MUST BE REPLACED------------
119 |
120 | def numBits(n):
121 | if n==0:
122 | return 0
123 | n= 1L * n; #convert to long, if it isn't already
124 | return n.__tojava__(java.math.BigInteger).bitLength()
125 |
126 | #Adjust the string to an array of bytes
127 | def stringToJavaByteArray(s):
128 | bytes = jarray.zeros(len(s), 'b')
129 | for count, c in enumerate(s):
130 | x = ord(c)
131 | if x >= 128: x -= 256
132 | bytes[count] = x
133 | return bytes
134 |
135 | BaseException = java.lang.Exception
136 | import sys
137 | import traceback
138 | def formatExceptionTrace(e):
139 | newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
140 | return newStr
--------------------------------------------------------------------------------
/intercom/twilio/rest/__init__.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | from twilio import TwilioException
4 | from twilio.rest.resources import make_request
5 | from twilio.rest.resources import Accounts
6 | from twilio.rest.resources import Applications
7 | from twilio.rest.resources import Calls
8 | from twilio.rest.resources import CallerIds
9 | from twilio.rest.resources import Notifications
10 | from twilio.rest.resources import Recordings
11 | from twilio.rest.resources import Transcriptions
12 | from twilio.rest.resources import Sms
13 | from twilio.rest.resources import Participants
14 | from twilio.rest.resources import PhoneNumbers
15 | from twilio.rest.resources import Conferences
16 | from twilio.rest.resources import Sandboxes
17 | from urllib import urlencode
18 | from urlparse import urljoin
19 |
20 |
21 | def find_credentials():
22 | """
23 | Look in the current environment for Twilio credentails
24 | """
25 | try:
26 | account = os.environ["TWILIO_ACCOUNT_SID"]
27 | token = os.environ["TWILIO_AUTH_TOKEN"]
28 | return account, token
29 | except KeyError:
30 | return None, None
31 |
32 |
33 | class TwilioRestClient(object):
34 | """
35 | A client for accessing the Twilio REST API
36 | """
37 |
38 | def request(self, path, method=None, vars=None):
39 | """sends a request and gets a response from the Twilio REST API
40 |
41 | .. deprecated:: 3.0
42 |
43 | :param path: the URL (relative to the endpoint URL, after the /v1
44 | :param url: the HTTP method to use, defaults to POST
45 | :param vars: for POST or PUT, a dict of data to send
46 |
47 | :returns: Twilio response in XML or raises an exception on error
48 |
49 | This method is only included for backwards compatability reasons.
50 | It will be removed in a future version
51 | """
52 | logging.warning(":meth:`TwilioRestClient.request` is deprecated and "
53 | "will be removed in a future version")
54 |
55 | vars = vars or {}
56 | params = None
57 | data = None
58 |
59 | if not path or len(path) < 1:
60 | raise ValueError('Invalid path parameter')
61 | if method and method not in ['GET', 'POST', 'DELETE', 'PUT']:
62 | raise NotImplementedError(
63 | 'HTTP %s method not implemented' % method)
64 |
65 | if path[0] == '/':
66 | uri = _TWILIO_API_URL + path
67 | else:
68 | uri = _TWILIO_API_URL + '/' + path
69 |
70 | if method == "GET":
71 | params = vars
72 | elif method == "POST" or method == "PUT":
73 | data = vars
74 |
75 | headers = {
76 | "User-Agent": "twilio-python",
77 | }
78 |
79 | resp = make_request(method, uri, auth=self.auth, data=data,
80 | params=params, headers=headers)
81 |
82 | return resp.content
83 |
84 | def __init__(self, account=None, token=None, base="https://api.twilio.com",
85 | version="2010-04-01", client=None):
86 | """
87 | Create a Twilio REST API client.
88 | """
89 |
90 | # Get account credentials
91 | if not account or not token:
92 | account, token = find_credentials()
93 | if not account or not token:
94 | raise TwilioException("Could not find account credentials")
95 |
96 | auth = (account, token)
97 | version_uri = "%s/%s" % (base, version)
98 | account_uri = "%s/%s/Accounts/%s" % (base, version, account)
99 |
100 | self.accounts = Accounts(version_uri, auth)
101 | self.applications = Applications(account_uri, auth)
102 | self.calls = Calls(account_uri, auth)
103 | self.caller_ids = CallerIds(account_uri, auth)
104 | self.notifications = Notifications(account_uri, auth)
105 | self.recordings = Recordings(account_uri, auth)
106 | self.transcriptions = Transcriptions(account_uri, auth)
107 | self.sms = Sms(account_uri, auth)
108 | self.phone_numbers = PhoneNumbers(account_uri, auth)
109 | self.conferences = Conferences(account_uri, auth)
110 | self.sandboxes = Sandboxes(account_uri, auth)
111 |
112 | self.auth = auth
113 | self.account_uri = account_uri
114 |
115 | def participants(self, conference_sid):
116 | """
117 | Return a :class:`Participants` instance for the :class:`Conference`
118 | with conference_sid,
119 | """
120 | base_uri = "%s/Conferences/%s" % (self.account_uri, conference_sid)
121 | return Participants(base_uri, self.auth)
122 |
123 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/X509.py:
--------------------------------------------------------------------------------
1 | """Class representing an X.509 certificate."""
2 |
3 | from utils.ASN1Parser import ASN1Parser
4 | from utils.cryptomath import *
5 | from utils.keyfactory import _createPublicRSAKey
6 |
7 |
8 | class X509:
9 | """This class represents an X.509 certificate.
10 |
11 | @type bytes: L{array.array} of unsigned bytes
12 | @ivar bytes: The DER-encoded ASN.1 certificate
13 |
14 | @type publicKey: L{tlslite.utils.RSAKey.RSAKey}
15 | @ivar publicKey: The subject public key from the certificate.
16 | """
17 |
18 | def __init__(self):
19 | self.bytes = createByteArraySequence([])
20 | self.publicKey = None
21 |
22 | def parse(self, s):
23 | """Parse a PEM-encoded X.509 certificate.
24 |
25 | @type s: str
26 | @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded
27 | certificate wrapped with "-----BEGIN CERTIFICATE-----" and
28 | "-----END CERTIFICATE-----" tags).
29 | """
30 |
31 | start = s.find("-----BEGIN CERTIFICATE-----")
32 | end = s.find("-----END CERTIFICATE-----")
33 | if start == -1:
34 | raise SyntaxError("Missing PEM prefix")
35 | if end == -1:
36 | raise SyntaxError("Missing PEM postfix")
37 | s = s[start+len("-----BEGIN CERTIFICATE-----") : end]
38 |
39 | bytes = base64ToBytes(s)
40 | self.parseBinary(bytes)
41 | return self
42 |
43 | def parseBinary(self, bytes):
44 | """Parse a DER-encoded X.509 certificate.
45 |
46 | @type bytes: str or L{array.array} of unsigned bytes
47 | @param bytes: A DER-encoded X.509 certificate.
48 | """
49 |
50 | if isinstance(bytes, type("")):
51 | bytes = stringToBytes(bytes)
52 |
53 | self.bytes = bytes
54 | p = ASN1Parser(bytes)
55 |
56 | #Get the tbsCertificate
57 | tbsCertificateP = p.getChild(0)
58 |
59 | #Is the optional version field present?
60 | #This determines which index the key is at.
61 | if tbsCertificateP.value[0]==0xA0:
62 | subjectPublicKeyInfoIndex = 6
63 | else:
64 | subjectPublicKeyInfoIndex = 5
65 |
66 | #Get the subjectPublicKeyInfo
67 | subjectPublicKeyInfoP = tbsCertificateP.getChild(\
68 | subjectPublicKeyInfoIndex)
69 |
70 | #Get the algorithm
71 | algorithmP = subjectPublicKeyInfoP.getChild(0)
72 | rsaOID = algorithmP.value
73 | if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
74 | raise SyntaxError("Unrecognized AlgorithmIdentifier")
75 |
76 | #Get the subjectPublicKey
77 | subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1)
78 |
79 | #Adjust for BIT STRING encapsulation
80 | if (subjectPublicKeyP.value[0] !=0):
81 | raise SyntaxError()
82 | subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:])
83 |
84 | #Get the modulus and exponent
85 | modulusP = subjectPublicKeyP.getChild(0)
86 | publicExponentP = subjectPublicKeyP.getChild(1)
87 |
88 | #Decode them into numbers
89 | n = bytesToNumber(modulusP.value)
90 | e = bytesToNumber(publicExponentP.value)
91 |
92 | #Create a public key instance
93 | self.publicKey = _createPublicRSAKey(n, e)
94 |
95 | def getFingerprint(self):
96 | """Get the hex-encoded fingerprint of this certificate.
97 |
98 | @rtype: str
99 | @return: A hex-encoded fingerprint.
100 | """
101 | return sha.sha(self.bytes).hexdigest()
102 |
103 | def getCommonName(self):
104 | """Get the Subject's Common Name from the certificate.
105 |
106 | The cryptlib_py module must be installed in order to use this
107 | function.
108 |
109 | @rtype: str or None
110 | @return: The CN component of the certificate's subject DN, if
111 | present.
112 | """
113 | import cryptlib_py
114 | import array
115 | c = cryptlib_py.cryptImportCert(self.bytes, cryptlib_py.CRYPT_UNUSED)
116 | name = cryptlib_py.CRYPT_CERTINFO_COMMONNAME
117 | try:
118 | try:
119 | length = cryptlib_py.cryptGetAttributeString(c, name, None)
120 | returnVal = array.array('B', [0] * length)
121 | cryptlib_py.cryptGetAttributeString(c, name, returnVal)
122 | returnVal = returnVal.tostring()
123 | except cryptlib_py.CryptException, e:
124 | if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND:
125 | returnVal = None
126 | return returnVal
127 | finally:
128 | cryptlib_py.cryptDestroyCert(c)
129 |
130 | def writeBytes(self):
131 | return self.bytes
132 |
133 |
134 |
--------------------------------------------------------------------------------
/intercom/atom/url.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 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 |
18 | __author__ = 'api.jscudder (Jeff Scudder)'
19 |
20 |
21 | import urlparse
22 | import urllib
23 |
24 |
25 | DEFAULT_PROTOCOL = 'http'
26 | DEFAULT_PORT = 80
27 |
28 |
29 | def parse_url(url_string):
30 | """Creates a Url object which corresponds to the URL string.
31 |
32 | This method can accept partial URLs, but it will leave missing
33 | members of the Url unset.
34 | """
35 | parts = urlparse.urlparse(url_string)
36 | url = Url()
37 | if parts[0]:
38 | url.protocol = parts[0]
39 | if parts[1]:
40 | host_parts = parts[1].split(':')
41 | if host_parts[0]:
42 | url.host = host_parts[0]
43 | if len(host_parts) > 1:
44 | url.port = host_parts[1]
45 | if parts[2]:
46 | url.path = parts[2]
47 | if parts[4]:
48 | param_pairs = parts[4].split('&')
49 | for pair in param_pairs:
50 | pair_parts = pair.split('=')
51 | if len(pair_parts) > 1:
52 | url.params[urllib.unquote_plus(pair_parts[0])] = (
53 | urllib.unquote_plus(pair_parts[1]))
54 | elif len(pair_parts) == 1:
55 | url.params[urllib.unquote_plus(pair_parts[0])] = None
56 | return url
57 |
58 | class Url(object):
59 | """Represents a URL and implements comparison logic.
60 |
61 | URL strings which are not identical can still be equivalent, so this object
62 | provides a better interface for comparing and manipulating URLs than
63 | strings. URL parameters are represented as a dictionary of strings, and
64 | defaults are used for the protocol (http) and port (80) if not provided.
65 | """
66 | def __init__(self, protocol=None, host=None, port=None, path=None,
67 | params=None):
68 | self.protocol = protocol
69 | self.host = host
70 | self.port = port
71 | self.path = path
72 | self.params = params or {}
73 |
74 | def to_string(self):
75 | url_parts = ['', '', '', '', '', '']
76 | if self.protocol:
77 | url_parts[0] = self.protocol
78 | if self.host:
79 | if self.port:
80 | url_parts[1] = ':'.join((self.host, str(self.port)))
81 | else:
82 | url_parts[1] = self.host
83 | if self.path:
84 | url_parts[2] = self.path
85 | if self.params:
86 | url_parts[4] = self.get_param_string()
87 | return urlparse.urlunparse(url_parts)
88 |
89 | def get_param_string(self):
90 | param_pairs = []
91 | for key, value in self.params.iteritems():
92 | param_pairs.append('='.join((urllib.quote_plus(key),
93 | urllib.quote_plus(str(value)))))
94 | return '&'.join(param_pairs)
95 |
96 | def get_request_uri(self):
97 | """Returns the path with the parameters escaped and appended."""
98 | param_string = self.get_param_string()
99 | if param_string:
100 | return '?'.join([self.path, param_string])
101 | else:
102 | return self.path
103 |
104 | def __cmp__(self, other):
105 | if not isinstance(other, Url):
106 | return cmp(self.to_string(), str(other))
107 | difference = 0
108 | # Compare the protocol
109 | if self.protocol and other.protocol:
110 | difference = cmp(self.protocol, other.protocol)
111 | elif self.protocol and not other.protocol:
112 | difference = cmp(self.protocol, DEFAULT_PROTOCOL)
113 | elif not self.protocol and other.protocol:
114 | difference = cmp(DEFAULT_PROTOCOL, other.protocol)
115 | if difference != 0:
116 | return difference
117 | # Compare the host
118 | difference = cmp(self.host, other.host)
119 | if difference != 0:
120 | return difference
121 | # Compare the port
122 | if self.port and other.port:
123 | difference = cmp(self.port, other.port)
124 | elif self.port and not other.port:
125 | difference = cmp(self.port, DEFAULT_PORT)
126 | elif not self.port and other.port:
127 | difference = cmp(DEFAULT_PORT, other.port)
128 | if difference != 0:
129 | return difference
130 | # Compare the path
131 | difference = cmp(self.path, other.path)
132 | if difference != 0:
133 | return difference
134 | # Compare the parameters
135 | return cmp(self.params, other.params)
136 |
137 | def __str__(self):
138 | return self.to_string()
139 |
140 |
--------------------------------------------------------------------------------
/intercom/gdata/oauth/rsa.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | """
4 | requires tlslite - http://trevp.net/tlslite/
5 |
6 | """
7 |
8 | import binascii
9 |
10 | from gdata.tlslite.utils import keyfactory
11 | from gdata.tlslite.utils import cryptomath
12 |
13 | # XXX andy: ugly local import due to module name, oauth.oauth
14 | import gdata.oauth as oauth
15 |
16 | class OAuthSignatureMethod_RSA_SHA1(oauth.OAuthSignatureMethod):
17 | def get_name(self):
18 | return "RSA-SHA1"
19 |
20 | def _fetch_public_cert(self, oauth_request):
21 | # not implemented yet, ideas are:
22 | # (1) do a lookup in a table of trusted certs keyed off of consumer
23 | # (2) fetch via http using a url provided by the requester
24 | # (3) some sort of specific discovery code based on request
25 | #
26 | # either way should return a string representation of the certificate
27 | raise NotImplementedError
28 |
29 | def _fetch_private_cert(self, oauth_request):
30 | # not implemented yet, ideas are:
31 | # (1) do a lookup in a table of trusted certs keyed off of consumer
32 | #
33 | # either way should return a string representation of the certificate
34 | raise NotImplementedError
35 |
36 | def build_signature_base_string(self, oauth_request, consumer, token):
37 | sig = (
38 | oauth.escape(oauth_request.get_normalized_http_method()),
39 | oauth.escape(oauth_request.get_normalized_http_url()),
40 | oauth.escape(oauth_request.get_normalized_parameters()),
41 | )
42 | key = ''
43 | raw = '&'.join(sig)
44 | return key, raw
45 |
46 | def build_signature(self, oauth_request, consumer, token):
47 | key, base_string = self.build_signature_base_string(oauth_request,
48 | consumer,
49 | token)
50 |
51 | # Fetch the private key cert based on the request
52 | cert = self._fetch_private_cert(oauth_request)
53 |
54 | # Pull the private key from the certificate
55 | privatekey = keyfactory.parsePrivateKey(cert)
56 |
57 | # Convert base_string to bytes
58 | #base_string_bytes = cryptomath.createByteArraySequence(base_string)
59 |
60 | # Sign using the key
61 | signed = privatekey.hashAndSign(base_string)
62 |
63 | return binascii.b2a_base64(signed)[:-1]
64 |
65 | def check_signature(self, oauth_request, consumer, token, signature):
66 | decoded_sig = base64.b64decode(signature);
67 |
68 | key, base_string = self.build_signature_base_string(oauth_request,
69 | consumer,
70 | token)
71 |
72 | # Fetch the public key cert based on the request
73 | cert = self._fetch_public_cert(oauth_request)
74 |
75 | # Pull the public key from the certificate
76 | publickey = keyfactory.parsePEMKey(cert, public=True)
77 |
78 | # Check the signature
79 | ok = publickey.hashAndVerify(decoded_sig, base_string)
80 |
81 | return ok
82 |
83 |
84 | class TestOAuthSignatureMethod_RSA_SHA1(OAuthSignatureMethod_RSA_SHA1):
85 | def _fetch_public_cert(self, oauth_request):
86 | cert = """
87 | -----BEGIN CERTIFICATE-----
88 | MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0
89 | IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV
90 | BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
91 | gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY
92 | zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb
93 | mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3
94 | DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d
95 | 4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb
96 | WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J
97 | -----END CERTIFICATE-----
98 | """
99 | return cert
100 |
101 | def _fetch_private_cert(self, oauth_request):
102 | cert = """
103 | -----BEGIN PRIVATE KEY-----
104 | MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V
105 | A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d
106 | 7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ
107 | hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H
108 | X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm
109 | uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw
110 | rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z
111 | zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn
112 | qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG
113 | WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno
114 | cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+
115 | 3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8
116 | AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54
117 | Lw03eHTNQghS0A==
118 | -----END PRIVATE KEY-----
119 | """
120 | return cert
121 |
--------------------------------------------------------------------------------
/intercom/atom/mock_http.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 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 |
18 | __author__ = 'api.jscudder (Jeff Scudder)'
19 |
20 |
21 | import atom.http_interface
22 | import atom.url
23 |
24 |
25 | class Error(Exception):
26 | pass
27 |
28 |
29 | class NoRecordingFound(Error):
30 | pass
31 |
32 |
33 | class MockRequest(object):
34 | """Holds parameters of an HTTP request for matching against future requests.
35 | """
36 | def __init__(self, operation, url, data=None, headers=None):
37 | self.operation = operation
38 | if isinstance(url, (str, unicode)):
39 | url = atom.url.parse_url(url)
40 | self.url = url
41 | self.data = data
42 | self.headers = headers
43 |
44 |
45 | class MockResponse(atom.http_interface.HttpResponse):
46 | """Simulates an httplib.HTTPResponse object."""
47 | def __init__(self, body=None, status=None, reason=None, headers=None):
48 | if body and hasattr(body, 'read'):
49 | self.body = body.read()
50 | else:
51 | self.body = body
52 | if status is not None:
53 | self.status = int(status)
54 | else:
55 | self.status = None
56 | self.reason = reason
57 | self._headers = headers or {}
58 |
59 | def read(self):
60 | return self.body
61 |
62 |
63 | class MockHttpClient(atom.http_interface.GenericHttpClient):
64 | def __init__(self, headers=None, recordings=None, real_client=None):
65 | """An HttpClient which responds to request with stored data.
66 |
67 | The request-response pairs are stored as tuples in a member list named
68 | recordings.
69 |
70 | The MockHttpClient can be switched from replay mode to record mode by
71 | setting the real_client member to an instance of an HttpClient which will
72 | make real HTTP requests and store the server's response in list of
73 | recordings.
74 |
75 | Args:
76 | headers: dict containing HTTP headers which should be included in all
77 | HTTP requests.
78 | recordings: The initial recordings to be used for responses. This list
79 | contains tuples in the form: (MockRequest, MockResponse)
80 | real_client: An HttpClient which will make a real HTTP request. The
81 | response will be converted into a MockResponse and stored in
82 | recordings.
83 | """
84 | self.recordings = recordings or []
85 | self.real_client = real_client
86 | self.headers = headers or {}
87 |
88 | def add_response(self, response, operation, url, data=None, headers=None):
89 | """Adds a request-response pair to the recordings list.
90 |
91 | After the recording is added, future matching requests will receive the
92 | response.
93 |
94 | Args:
95 | response: MockResponse
96 | operation: str
97 | url: str
98 | data: str, Currently the data is ignored when looking for matching
99 | requests.
100 | headers: dict of strings: Currently the headers are ignored when
101 | looking for matching requests.
102 | """
103 | request = MockRequest(operation, url, data=data, headers=headers)
104 | self.recordings.append((request, response))
105 |
106 | def request(self, operation, url, data=None, headers=None):
107 | """Returns a matching MockResponse from the recordings.
108 |
109 | If the real_client is set, the request will be passed along and the
110 | server's response will be added to the recordings and also returned.
111 |
112 | If there is no match, a NoRecordingFound error will be raised.
113 | """
114 | if self.real_client is None:
115 | if isinstance(url, (str, unicode)):
116 | url = atom.url.parse_url(url)
117 | for recording in self.recordings:
118 | if recording[0].operation == operation and recording[0].url == url:
119 | return recording[1]
120 | raise NoRecordingFound('No recodings found for %s %s' % (
121 | operation, url))
122 | else:
123 | # There is a real HTTP client, so make the request, and record the
124 | # response.
125 | response = self.real_client.request(operation, url, data=data,
126 | headers=headers)
127 | # TODO: copy the headers
128 | stored_response = MockResponse(body=response, status=response.status,
129 | reason=response.reason)
130 | self.add_response(stored_response, operation, url, data=data,
131 | headers=headers)
132 | return stored_response
133 |
--------------------------------------------------------------------------------
/intercom/gdata/apps/migration/service.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright (C) 2008 Google.
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 | """Contains the methods to import mail via Google Apps Email Migration API.
18 |
19 | MigrationService: Provides methids to import mail.
20 | """
21 |
22 | __author__ = 'google-apps-apis@googlegroups.com'
23 |
24 |
25 | import base64
26 | import gdata
27 | import gdata.apps.service
28 | import gdata.service
29 | from gdata.apps import migration
30 |
31 |
32 | API_VER = '2.0'
33 |
34 |
35 | class MigrationService(gdata.apps.service.AppsService):
36 | """Client for the EMAPI migration service. Use either ImportMail to import
37 | one message at a time, or AddBatchEntry and SubmitBatch to import a batch of
38 | messages at a time.
39 | """
40 | def __init__(self, email=None, password=None, domain=None, source=None,
41 | server='apps-apis.google.com', additional_headers=None):
42 | gdata.apps.service.AppsService.__init__(
43 | self, email=email, password=password, domain=domain, source=source,
44 | server=server, additional_headers=additional_headers)
45 | self.mail_batch = migration.BatchMailEventFeed()
46 |
47 | def _BaseURL(self):
48 | return '/a/feeds/migration/%s/%s' % (API_VER, self.domain)
49 |
50 | def ImportMail(self, user_name, mail_message, mail_item_properties,
51 | mail_labels):
52 | """Import a single mail message.
53 |
54 | Args:
55 | user_name: The username to import messages to.
56 | mail_message: An RFC822 format email message.
57 | mail_item_properties: A list of Gmail properties to apply to the message.
58 | mail_labels: A list of labels to apply to the message.
59 |
60 | Returns:
61 | A MailEntry representing the successfully imported message.
62 |
63 | Raises:
64 | AppsForYourDomainException: An error occurred importing the message.
65 | """
66 | uri = '%s/%s/mail' % (self._BaseURL(), user_name)
67 |
68 | mail_entry = migration.MailEntry()
69 | mail_entry.rfc822_msg = migration.Rfc822Msg(text=(base64.b64encode(
70 | mail_message)))
71 | mail_entry.rfc822_msg.encoding = 'base64'
72 | mail_entry.mail_item_property = map(
73 | lambda x: migration.MailItemProperty(value=x), mail_item_properties)
74 | mail_entry.label = map(lambda x: migration.Label(label_name=x),
75 | mail_labels)
76 |
77 | try:
78 | return migration.MailEntryFromString(str(self.Post(mail_entry, uri)))
79 | except gdata.service.RequestError, e:
80 | raise gdata.apps.service.AppsForYourDomainException(e.args[0])
81 |
82 | def AddBatchEntry(self, mail_message, mail_item_properties,
83 | mail_labels):
84 | """Add a message to the current batch that you later will submit.
85 |
86 | Args:
87 | mail_message: An RFC822 format email message.
88 | mail_item_properties: A list of Gmail properties to apply to the message.
89 | mail_labels: A list of labels to apply to the message.
90 |
91 | Returns:
92 | The length of the MailEntry representing the message.
93 | """
94 | mail_entry = migration.BatchMailEntry()
95 | mail_entry.rfc822_msg = migration.Rfc822Msg(text=(base64.b64encode(
96 | mail_message)))
97 | mail_entry.rfc822_msg.encoding = 'base64'
98 | mail_entry.mail_item_property = map(
99 | lambda x: migration.MailItemProperty(value=x), mail_item_properties)
100 | mail_entry.label = map(lambda x: migration.Label(label_name=x),
101 | mail_labels)
102 |
103 | self.mail_batch.AddBatchEntry(mail_entry)
104 |
105 | return len(str(mail_entry))
106 |
107 | def SubmitBatch(self, user_name):
108 | """Send a all the mail items you have added to the batch to the server.
109 |
110 | Args:
111 | user_name: The username to import messages to.
112 |
113 | Returns:
114 | A HTTPResponse from the web service call.
115 |
116 | Raises:
117 | AppsForYourDomainException: An error occurred importing the batch.
118 | """
119 | uri = '%s/%s/mail/batch' % (self._BaseURL(), user_name)
120 |
121 | try:
122 | self.result = self.Post(self.mail_batch, uri,
123 | converter=migration.BatchMailEventFeedFromString)
124 | except gdata.service.RequestError, e:
125 | raise gdata.apps.service.AppsForYourDomainException(e.args[0])
126 |
127 | self.mail_batch = migration.BatchMailEventFeed()
128 |
129 | return self.result
130 |
--------------------------------------------------------------------------------
/intercom/gdata/codesearch/service.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright (c) 2007 Benoit Chesneau
4 | #
5 | # Permission to use, copy, modify, and distribute this software for any
6 | # purpose with or without fee is hereby granted, provided that the above
7 | # copyright notice and this permission notice appear in all copies.
8 | #
9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
17 |
18 | """CodesearchService extends GDataService to streamline Google Codesearch
19 | operations"""
20 |
21 |
22 | __author__ = 'Benoit Chesneau'
23 |
24 |
25 | import atom
26 | import gdata.service
27 | import gdata.codesearch
28 |
29 |
30 | class CodesearchService(gdata.service.GDataService):
31 | """Client extension for Google codesearch service"""
32 | ssl = True
33 |
34 | def __init__(self, email=None, password=None, source=None,
35 | server='www.google.com', additional_headers=None, **kwargs):
36 | """Creates a client for the Google codesearch service.
37 |
38 | Args:
39 | email: string (optional) The user's email address, used for
40 | authentication.
41 | password: string (optional) The user's password.
42 | source: string (optional) The name of the user's application.
43 | server: string (optional) The name of the server to which a connection
44 | will be opened. Default value: 'www.google.com'.
45 | **kwargs: The other parameters to pass to gdata.service.GDataService
46 | constructor.
47 | """
48 | gdata.service.GDataService.__init__(
49 | self, email=email, password=password, service='codesearch',
50 | source=source, server=server, additional_headers=additional_headers,
51 | **kwargs)
52 |
53 | def Query(self, uri, converter=gdata.codesearch.CodesearchFeedFromString):
54 | """Queries the Codesearch feed and returns the resulting feed of
55 | entries.
56 |
57 | Args:
58 | uri: string The full URI to be queried. This can contain query
59 | parameters, a hostname, or simply the relative path to a Document
60 | List feed. The DocumentQuery object is useful when constructing
61 | query parameters.
62 | converter: func (optional) A function which will be executed on the
63 | retrieved item, generally to render it into a Python object.
64 | By default the CodesearchFeedFromString function is used to
65 | return a CodesearchFeed object. This is because most feed
66 | queries will result in a feed and not a single entry.
67 |
68 | Returns :
69 | A CodesearchFeed objects representing the feed returned by the server
70 | """
71 | return self.Get(uri, converter=converter)
72 |
73 | def GetSnippetsFeed(self, text_query=None):
74 | """Retrieve Codesearch feed for a keyword
75 |
76 | Args:
77 | text_query : string (optional) The contents of the q query parameter. This
78 | string is URL escaped upon conversion to a URI.
79 | Returns:
80 | A CodesearchFeed objects representing the feed returned by the server
81 | """
82 |
83 | query=gdata.codesearch.service.CodesearchQuery(text_query=text_query)
84 | feed = self.Query(query.ToUri())
85 | return feed
86 |
87 |
88 | class CodesearchQuery(gdata.service.Query):
89 | """Object used to construct the query to the Google Codesearch feed. here only as a shorcut"""
90 |
91 | def __init__(self, feed='/codesearch/feeds/search', text_query=None,
92 | params=None, categories=None):
93 | """Constructor for Codesearch Query.
94 |
95 | Args:
96 | feed: string (optional) The path for the feed. (e.g. '/codesearch/feeds/search')
97 | text_query: string (optional) The contents of the q query parameter. This
98 | string is URL escaped upon conversion to a URI.
99 | params: dict (optional) Parameter value string pairs which become URL
100 | params when translated to a URI. These parameters are added to
101 | the query's items.
102 | categories: list (optional) List of category strings which should be
103 | included as query categories. See gdata.service.Query for
104 | additional documentation.
105 |
106 | Yelds:
107 | A CodesearchQuery object to construct a URI based on Codesearch feed
108 | """
109 |
110 | gdata.service.Query.__init__(self, feed, text_query, params, categories)
111 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/integration/SMTP_TLS.py:
--------------------------------------------------------------------------------
1 | """TLS Lite + smtplib."""
2 |
3 | from smtplib import SMTP
4 | from gdata.tlslite.TLSConnection import TLSConnection
5 | from gdata.tlslite.integration.ClientHelper import ClientHelper
6 |
7 | class SMTP_TLS(SMTP):
8 | """This class extends L{smtplib.SMTP} with TLS support."""
9 |
10 | def starttls(self,
11 | username=None, password=None, sharedKey=None,
12 | certChain=None, privateKey=None,
13 | cryptoID=None, protocol=None,
14 | x509Fingerprint=None,
15 | x509TrustList=None, x509CommonName=None,
16 | settings=None):
17 | """Puts the connection to the SMTP server into TLS mode.
18 |
19 | If the server supports TLS, this will encrypt the rest of the SMTP
20 | session.
21 |
22 | For client authentication, use one of these argument
23 | combinations:
24 | - username, password (SRP)
25 | - username, sharedKey (shared-key)
26 | - certChain, privateKey (certificate)
27 |
28 | For server authentication, you can either rely on the
29 | implicit mutual authentication performed by SRP or
30 | shared-keys, or you can do certificate-based server
31 | authentication with one of these argument combinations:
32 | - cryptoID[, protocol] (requires cryptoIDlib)
33 | - x509Fingerprint
34 | - x509TrustList[, x509CommonName] (requires cryptlib_py)
35 |
36 | Certificate-based server authentication is compatible with
37 | SRP or certificate-based client authentication. It is
38 | not compatible with shared-keys.
39 |
40 | The caller should be prepared to handle TLS-specific
41 | exceptions. See the client handshake functions in
42 | L{tlslite.TLSConnection.TLSConnection} for details on which
43 | exceptions might be raised.
44 |
45 | @type username: str
46 | @param username: SRP or shared-key username. Requires the
47 | 'password' or 'sharedKey' argument.
48 |
49 | @type password: str
50 | @param password: SRP password for mutual authentication.
51 | Requires the 'username' argument.
52 |
53 | @type sharedKey: str
54 | @param sharedKey: Shared key for mutual authentication.
55 | Requires the 'username' argument.
56 |
57 | @type certChain: L{tlslite.X509CertChain.X509CertChain} or
58 | L{cryptoIDlib.CertChain.CertChain}
59 | @param certChain: Certificate chain for client authentication.
60 | Requires the 'privateKey' argument. Excludes the SRP or
61 | shared-key related arguments.
62 |
63 | @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
64 | @param privateKey: Private key for client authentication.
65 | Requires the 'certChain' argument. Excludes the SRP or
66 | shared-key related arguments.
67 |
68 | @type cryptoID: str
69 | @param cryptoID: cryptoID for server authentication. Mutually
70 | exclusive with the 'x509...' arguments.
71 |
72 | @type protocol: str
73 | @param protocol: cryptoID protocol URI for server
74 | authentication. Requires the 'cryptoID' argument.
75 |
76 | @type x509Fingerprint: str
77 | @param x509Fingerprint: Hex-encoded X.509 fingerprint for
78 | server authentication. Mutually exclusive with the 'cryptoID'
79 | and 'x509TrustList' arguments.
80 |
81 | @type x509TrustList: list of L{tlslite.X509.X509}
82 | @param x509TrustList: A list of trusted root certificates. The
83 | other party must present a certificate chain which extends to
84 | one of these root certificates. The cryptlib_py module must be
85 | installed to use this parameter. Mutually exclusive with the
86 | 'cryptoID' and 'x509Fingerprint' arguments.
87 |
88 | @type x509CommonName: str
89 | @param x509CommonName: The end-entity certificate's 'CN' field
90 | must match this value. For a web server, this is typically a
91 | server name such as 'www.amazon.com'. Mutually exclusive with
92 | the 'cryptoID' and 'x509Fingerprint' arguments. Requires the
93 | 'x509TrustList' argument.
94 |
95 | @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
96 | @param settings: Various settings which can be used to control
97 | the ciphersuites, certificate types, and SSL/TLS versions
98 | offered by the client.
99 | """
100 | (resp, reply) = self.docmd("STARTTLS")
101 | if resp == 220:
102 | helper = ClientHelper(
103 | username, password, sharedKey,
104 | certChain, privateKey,
105 | cryptoID, protocol,
106 | x509Fingerprint,
107 | x509TrustList, x509CommonName,
108 | settings)
109 | conn = TLSConnection(self.sock)
110 | conn.closeSocket = True
111 | helper._handshake(conn)
112 | self.sock = conn
113 | self.file = conn.makefile('rb')
114 | return (resp, reply)
115 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/Session.py:
--------------------------------------------------------------------------------
1 | """Class representing a TLS session."""
2 |
3 | from utils.compat import *
4 | from mathtls import *
5 | from constants import *
6 |
7 | class Session:
8 | """
9 | This class represents a TLS session.
10 |
11 | TLS distinguishes between connections and sessions. A new
12 | handshake creates both a connection and a session. Data is
13 | transmitted over the connection.
14 |
15 | The session contains a more permanent record of the handshake. The
16 | session can be inspected to determine handshake results. The
17 | session can also be used to create a new connection through
18 | "session resumption". If the client and server both support this,
19 | they can create a new connection based on an old session without
20 | the overhead of a full handshake.
21 |
22 | The session for a L{tlslite.TLSConnection.TLSConnection} can be
23 | retrieved from the connection's 'session' attribute.
24 |
25 | @type srpUsername: str
26 | @ivar srpUsername: The client's SRP username (or None).
27 |
28 | @type sharedKeyUsername: str
29 | @ivar sharedKeyUsername: The client's shared-key username (or
30 | None).
31 |
32 | @type clientCertChain: L{tlslite.X509CertChain.X509CertChain} or
33 | L{cryptoIDlib.CertChain.CertChain}
34 | @ivar clientCertChain: The client's certificate chain (or None).
35 |
36 | @type serverCertChain: L{tlslite.X509CertChain.X509CertChain} or
37 | L{cryptoIDlib.CertChain.CertChain}
38 | @ivar serverCertChain: The server's certificate chain (or None).
39 | """
40 |
41 | def __init__(self):
42 | self.masterSecret = createByteArraySequence([])
43 | self.sessionID = createByteArraySequence([])
44 | self.cipherSuite = 0
45 | self.srpUsername = None
46 | self.sharedKeyUsername = None
47 | self.clientCertChain = None
48 | self.serverCertChain = None
49 | self.resumable = False
50 | self.sharedKey = False
51 |
52 | def _clone(self):
53 | other = Session()
54 | other.masterSecret = self.masterSecret
55 | other.sessionID = self.sessionID
56 | other.cipherSuite = self.cipherSuite
57 | other.srpUsername = self.srpUsername
58 | other.sharedKeyUsername = self.sharedKeyUsername
59 | other.clientCertChain = self.clientCertChain
60 | other.serverCertChain = self.serverCertChain
61 | other.resumable = self.resumable
62 | other.sharedKey = self.sharedKey
63 | return other
64 |
65 | def _calcMasterSecret(self, version, premasterSecret, clientRandom,
66 | serverRandom):
67 | if version == (3,0):
68 | self.masterSecret = PRF_SSL(premasterSecret,
69 | concatArrays(clientRandom, serverRandom), 48)
70 | elif version in ((3,1), (3,2)):
71 | self.masterSecret = PRF(premasterSecret, "master secret",
72 | concatArrays(clientRandom, serverRandom), 48)
73 | else:
74 | raise AssertionError()
75 |
76 | def valid(self):
77 | """If this session can be used for session resumption.
78 |
79 | @rtype: bool
80 | @return: If this session can be used for session resumption.
81 | """
82 | return self.resumable or self.sharedKey
83 |
84 | def _setResumable(self, boolean):
85 | #Only let it be set if this isn't a shared key
86 | if not self.sharedKey:
87 | #Only let it be set to True if the sessionID is non-null
88 | if (not boolean) or (boolean and self.sessionID):
89 | self.resumable = boolean
90 |
91 | def getCipherName(self):
92 | """Get the name of the cipher used with this connection.
93 |
94 | @rtype: str
95 | @return: The name of the cipher used with this connection.
96 | Either 'aes128', 'aes256', 'rc4', or '3des'.
97 | """
98 | if self.cipherSuite in CipherSuite.aes128Suites:
99 | return "aes128"
100 | elif self.cipherSuite in CipherSuite.aes256Suites:
101 | return "aes256"
102 | elif self.cipherSuite in CipherSuite.rc4Suites:
103 | return "rc4"
104 | elif self.cipherSuite in CipherSuite.tripleDESSuites:
105 | return "3des"
106 | else:
107 | return None
108 |
109 | def _createSharedKey(self, sharedKeyUsername, sharedKey):
110 | if len(sharedKeyUsername)>16:
111 | raise ValueError()
112 | if len(sharedKey)>47:
113 | raise ValueError()
114 |
115 | self.sharedKeyUsername = sharedKeyUsername
116 |
117 | self.sessionID = createByteArrayZeros(16)
118 | for x in range(len(sharedKeyUsername)):
119 | self.sessionID[x] = ord(sharedKeyUsername[x])
120 |
121 | premasterSecret = createByteArrayZeros(48)
122 | sharedKey = chr(len(sharedKey)) + sharedKey
123 | for x in range(48):
124 | premasterSecret[x] = ord(sharedKey[x % len(sharedKey)])
125 |
126 | self.masterSecret = PRF(premasterSecret, "shared secret",
127 | createByteArraySequence([]), 48)
128 | self.sharedKey = True
129 | return self
130 |
131 |
132 |
--------------------------------------------------------------------------------
/intercom/gdata/blogger/data.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright (C) 2009 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 |
18 | """Data model classes for parsing and generating XML for the Blogger API."""
19 |
20 |
21 | __author__ = 'j.s@google.com (Jeff Scudder)'
22 |
23 |
24 | import re
25 | import urlparse
26 | import atom.core
27 | import gdata.data
28 |
29 |
30 | LABEL_SCHEME = 'http://www.blogger.com/atom/ns#'
31 | THR_TEMPLATE = '{http://purl.org/syndication/thread/1.0}%s'
32 |
33 | BLOG_NAME_PATTERN = re.compile('(http://)(\w*)')
34 | BLOG_ID_PATTERN = re.compile('(tag:blogger.com,1999:blog-)(\w*)')
35 | BLOG_ID2_PATTERN = re.compile('tag:blogger.com,1999:user-(\d+)\.blog-(\d+)')
36 | POST_ID_PATTERN = re.compile(
37 | '(tag:blogger.com,1999:blog-)(\w*)(.post-)(\w*)')
38 | PAGE_ID_PATTERN = re.compile(
39 | '(tag:blogger.com,1999:blog-)(\w*)(.page-)(\w*)')
40 | COMMENT_ID_PATTERN = re.compile('.*-(\w*)$')
41 |
42 |
43 | class BloggerEntry(gdata.data.GDEntry):
44 | """Adds convenience methods inherited by all Blogger entries."""
45 |
46 | def get_blog_id(self):
47 | """Extracts the Blogger id of this blog.
48 |
49 | This method is useful when contructing URLs by hand. The blog id is
50 | often used in blogger operation URLs. This should not be confused with
51 | the id member of a BloggerBlog. The id element is the Atom id XML element.
52 | The blog id which this method returns is a part of the Atom id.
53 |
54 | Returns:
55 | The blog's unique id as a string.
56 | """
57 | if self.id.text:
58 | match = BLOG_ID_PATTERN.match(self.id.text)
59 | if match:
60 | return match.group(2)
61 | else:
62 | return BLOG_ID2_PATTERN.match(self.id.text).group(2)
63 | return None
64 |
65 | GetBlogId = get_blog_id
66 |
67 | def get_blog_name(self):
68 | """Finds the name of this blog as used in the 'alternate' URL.
69 |
70 | An alternate URL is in the form 'http://blogName.blogspot.com/'. For an
71 | entry representing the above example, this method would return 'blogName'.
72 |
73 | Returns:
74 | The blog's URL name component as a string.
75 | """
76 | for link in self.link:
77 | if link.rel == 'alternate':
78 | return urlparse.urlparse(link.href)[1].split(".", 1)[0]
79 | return None
80 |
81 | GetBlogName = get_blog_name
82 |
83 |
84 | class Blog(BloggerEntry):
85 | """Represents a blog which belongs to the user."""
86 |
87 |
88 | class BlogFeed(gdata.data.GDFeed):
89 | entry = [Blog]
90 |
91 |
92 | class BlogPost(BloggerEntry):
93 | """Represents a single post on a blog."""
94 |
95 | def add_label(self, label):
96 | """Adds a label to the blog post.
97 |
98 | The label is represented by an Atom category element, so this method
99 | is shorthand for appending a new atom.Category object.
100 |
101 | Args:
102 | label: str
103 | """
104 | self.category.append(atom.data.Category(scheme=LABEL_SCHEME, term=label))
105 |
106 | AddLabel = add_label
107 |
108 | def get_post_id(self):
109 | """Extracts the postID string from the entry's Atom id.
110 |
111 | Returns: A string of digits which identify this post within the blog.
112 | """
113 | if self.id.text:
114 | return POST_ID_PATTERN.match(self.id.text).group(4)
115 | return None
116 |
117 | GetPostId = get_post_id
118 |
119 |
120 | class BlogPostFeed(gdata.data.GDFeed):
121 | entry = [BlogPost]
122 |
123 |
124 | class BlogPage(BloggerEntry):
125 | """Represents a single page on a blog."""
126 |
127 | def get_page_id(self):
128 | """Extracts the pageID string from entry's Atom id.
129 |
130 | Returns: A string of digits which identify this post within the blog.
131 | """
132 | if self.id.text:
133 | return PAGE_ID_PATTERN.match(self.id.text).group(4)
134 | return None
135 |
136 | GetPageId = get_page_id
137 |
138 |
139 | class BlogPageFeed(gdata.data.GDFeed):
140 | entry = [BlogPage]
141 |
142 |
143 | class InReplyTo(atom.core.XmlElement):
144 | _qname = THR_TEMPLATE % 'in-reply-to'
145 | href = 'href'
146 | ref = 'ref'
147 | source = 'source'
148 | type = 'type'
149 |
150 |
151 | class Comment(BloggerEntry):
152 | """Blog post comment entry in a feed listing comments on a post or blog."""
153 | in_reply_to = InReplyTo
154 |
155 | def get_comment_id(self):
156 | """Extracts the commentID string from the entry's Atom id.
157 |
158 | Returns: A string of digits which identify this post within the blog.
159 | """
160 | if self.id.text:
161 | return COMMENT_ID_PATTERN.match(self.id.text).group(1)
162 | return None
163 |
164 | GetCommentId = get_comment_id
165 |
166 |
167 | class CommentFeed(gdata.data.GDFeed):
168 | entry = [Comment]
169 |
--------------------------------------------------------------------------------
/intercom/twilio/util.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hmac
3 | import time
4 | import urllib
5 | from hashlib import sha1
6 |
7 | try:
8 | import jwt
9 | except:
10 | from twilio.contrib import jwt
11 |
12 |
13 | class RequestValidator(object):
14 |
15 | def __init__(self, token):
16 | self.token = token
17 |
18 | def compute_signature(self, uri, params):
19 | """Compute the signature for a given request
20 |
21 | :param uri: full URI that Twilio requested on your server
22 | :param params: post vars that Twilio sent with the request
23 | :param auth: tuple with (account_sid, token)
24 |
25 | :returns: The computed signature
26 | """
27 | s = uri
28 | if len(params) > 0:
29 | for k, v in sorted(params.items()):
30 | s += k + v
31 |
32 | # compute signature and compare signatures
33 | computed = base64.encodestring(hmac.new(self.token, s, sha1).digest())
34 | return computed.strip()
35 |
36 | def validate(self, uri, params, signature):
37 | """Validate a request from Twilio
38 |
39 | :param uri: full URI that Twilio requested on your server
40 | :param params: post vars that Twilio sent with the request
41 | :param signature: expexcted signature in HTTP X-Twilio-Signature header
42 | :param auth: tuple with (account_sid, token)
43 |
44 | :returns: True if the request passes validation, False if not
45 | """
46 | return self.compute_signature(uri, params) == signature
47 |
48 |
49 | class TwilioCapability(object):
50 | """
51 | A token to control permissions with Twilio Client
52 |
53 | :param string account_sid: the account sid to which this token
54 | is granted access
55 | :param string auth_token: the secret key used to sign the token.
56 | Note, this auth token is not visible to the
57 | user of the token.
58 |
59 | :returns: A new TwilioCapability with zero permissions
60 | """
61 |
62 | def __init__(self, account_sid, auth_token):
63 | self.account_sid = account_sid
64 | self.auth_token = auth_token
65 | self.capabilities = {}
66 | self.client_name = None
67 |
68 | def payload(self):
69 | """Return the payload for this token."""
70 | if "outgoing" in self.capabilities and self.client_name is not None:
71 | scope = self.capabilities["outgoing"]
72 | scope.params["clientName"] = self.client_name
73 |
74 | capabilities = self.capabilities.values()
75 | scope_uris = [str(scope_uri) for scope_uri in capabilities]
76 |
77 | return {
78 | "scope": " ".join(scope_uris)
79 | }
80 |
81 | def generate(self, expires=3600):
82 | """Generate a valid JWT token with an expiration date.
83 |
84 | :param int expires: The token lifetime, in seconds. Defaults to
85 | 1 hour (3600)
86 |
87 | """
88 | payload = self.payload()
89 | payload['iss'] = self.account_sid
90 | payload['exp'] = int(time.time() + expires)
91 | return jwt.encode(payload, self.auth_token, "HS256")
92 |
93 | def allow_client_outgoing(self, application_sid, **kwargs):
94 | """Allow the user of this token to make outgoing connections.
95 |
96 | Keyword arguments are passed to the application.
97 |
98 | :param string application_sid: Application to contact
99 | """
100 | scope_params = {
101 | "appSid": application_sid,
102 | }
103 | if kwargs:
104 | scope_params["appParams"] = urllib.urlencode(kwargs, doseq=True)
105 |
106 | self.capabilities["outgoing"] = ScopeURI("client", "outgoing",
107 | scope_params)
108 |
109 | def allow_client_incoming(self, client_name):
110 | """If the user of this token should be allowed to accept incoming
111 | connections then configure the TwilioCapability through this method and
112 | specify the client name.
113 |
114 | :param string client_name: Client name to accept calls from
115 |
116 | """
117 | self.client_name = client_name
118 | self.capabilities["incoming"] = ScopeURI("client", "incoming", {
119 | 'clientName': client_name
120 | })
121 |
122 | def allow_event_stream(self, **kwargs):
123 | """Allow the user of this token to access their event stream."""
124 | scope_params = {
125 | "path": "/2010-04-01/Events",
126 | }
127 | if kwargs:
128 | scope_params['params'] = urllib.urlencode(kwargs, doseq=True)
129 |
130 | self.capabilities["events"] = ScopeURI("stream", "subscribe",
131 | scope_params)
132 |
133 |
134 | class ScopeURI(object):
135 |
136 | def __init__(self, service, privilege, params=None):
137 | self.service = service
138 | self.privilege = privilege
139 | self.params = params
140 |
141 | def __str__(self):
142 | params = urllib.urlencode(self.params) if self.params else None
143 | param_string = "?%s" % params if params else ''
144 | return "scope:%s:%s%s" % (self.service, self.privilege, param_string)
145 |
--------------------------------------------------------------------------------
/intercom/gdata/tlslite/integration/TLSAsyncDispatcherMixIn.py:
--------------------------------------------------------------------------------
1 | """TLS Lite + asyncore."""
2 |
3 |
4 | import asyncore
5 | from gdata.tlslite.TLSConnection import TLSConnection
6 | from AsyncStateMachine import AsyncStateMachine
7 |
8 |
9 | class TLSAsyncDispatcherMixIn(AsyncStateMachine):
10 | """This class can be "mixed in" with an
11 | L{asyncore.dispatcher} to add TLS support.
12 |
13 | This class essentially sits between the dispatcher and the select
14 | loop, intercepting events and only calling the dispatcher when
15 | applicable.
16 |
17 | In the case of handle_read(), a read operation will be activated,
18 | and when it completes, the bytes will be placed in a buffer where
19 | the dispatcher can retrieve them by calling recv(), and the
20 | dispatcher's handle_read() will be called.
21 |
22 | In the case of handle_write(), the dispatcher's handle_write() will
23 | be called, and when it calls send(), a write operation will be
24 | activated.
25 |
26 | To use this class, you must combine it with an asyncore.dispatcher,
27 | and pass in a handshake operation with setServerHandshakeOp().
28 |
29 | Below is an example of using this class with medusa. This class is
30 | mixed in with http_channel to create http_tls_channel. Note:
31 | 1. the mix-in is listed first in the inheritance list
32 |
33 | 2. the input buffer size must be at least 16K, otherwise the
34 | dispatcher might not read all the bytes from the TLS layer,
35 | leaving some bytes in limbo.
36 |
37 | 3. IE seems to have a problem receiving a whole HTTP response in a
38 | single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't
39 | be displayed on IE.
40 |
41 | Add the following text into 'start_medusa.py', in the 'HTTP Server'
42 | section::
43 |
44 | from tlslite.api import *
45 | s = open("./serverX509Cert.pem").read()
46 | x509 = X509()
47 | x509.parse(s)
48 | certChain = X509CertChain([x509])
49 |
50 | s = open("./serverX509Key.pem").read()
51 | privateKey = parsePEMKey(s, private=True)
52 |
53 | class http_tls_channel(TLSAsyncDispatcherMixIn,
54 | http_server.http_channel):
55 | ac_in_buffer_size = 16384
56 |
57 | def __init__ (self, server, conn, addr):
58 | http_server.http_channel.__init__(self, server, conn, addr)
59 | TLSAsyncDispatcherMixIn.__init__(self, conn)
60 | self.tlsConnection.ignoreAbruptClose = True
61 | self.setServerHandshakeOp(certChain=certChain,
62 | privateKey=privateKey)
63 |
64 | hs.channel_class = http_tls_channel
65 |
66 | If the TLS layer raises an exception, the exception will be caught
67 | in asyncore.dispatcher, which will call close() on this class. The
68 | TLS layer always closes the TLS connection before raising an
69 | exception, so the close operation will complete right away, causing
70 | asyncore.dispatcher.close() to be called, which closes the socket
71 | and removes this instance from the asyncore loop.
72 |
73 | """
74 |
75 |
76 | def __init__(self, sock=None):
77 | AsyncStateMachine.__init__(self)
78 |
79 | if sock:
80 | self.tlsConnection = TLSConnection(sock)
81 |
82 | #Calculate the sibling I'm being mixed in with.
83 | #This is necessary since we override functions
84 | #like readable(), handle_read(), etc., but we
85 | #also want to call the sibling's versions.
86 | for cl in self.__class__.__bases__:
87 | if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
88 | self.siblingClass = cl
89 | break
90 | else:
91 | raise AssertionError()
92 |
93 | def readable(self):
94 | result = self.wantsReadEvent()
95 | if result != None:
96 | return result
97 | return self.siblingClass.readable(self)
98 |
99 | def writable(self):
100 | result = self.wantsWriteEvent()
101 | if result != None:
102 | return result
103 | return self.siblingClass.writable(self)
104 |
105 | def handle_read(self):
106 | self.inReadEvent()
107 |
108 | def handle_write(self):
109 | self.inWriteEvent()
110 |
111 | def outConnectEvent(self):
112 | self.siblingClass.handle_connect(self)
113 |
114 | def outCloseEvent(self):
115 | asyncore.dispatcher.close(self)
116 |
117 | def outReadEvent(self, readBuffer):
118 | self.readBuffer = readBuffer
119 | self.siblingClass.handle_read(self)
120 |
121 | def outWriteEvent(self):
122 | self.siblingClass.handle_write(self)
123 |
124 | def recv(self, bufferSize=16384):
125 | if bufferSize < 16384 or self.readBuffer == None:
126 | raise AssertionError()
127 | returnValue = self.readBuffer
128 | self.readBuffer = None
129 | return returnValue
130 |
131 | def send(self, writeBuffer):
132 | self.setWriteOp(writeBuffer)
133 | return len(writeBuffer)
134 |
135 | def close(self):
136 | if hasattr(self, "tlsConnection"):
137 | self.setCloseOp()
138 | else:
139 | asyncore.dispatcher.close(self)
140 |
--------------------------------------------------------------------------------
/intercom/gdata/codesearch/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright (c) 2007 Benoit Chesneau
4 | #
5 | # Permission to use, copy, modify, and distribute this software for any
6 | # purpose with or without fee is hereby granted, provided that the above
7 | # copyright notice and this permission notice appear in all copies.
8 | #
9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
17 |
18 | """Contains extensions to Atom objects used by Google Codesearch"""
19 |
20 | __author__ = 'Benoit Chesneau'
21 |
22 |
23 | import atom
24 | import gdata
25 |
26 |
27 | CODESEARCH_NAMESPACE='http://schemas.google.com/codesearch/2006'
28 | CODESEARCH_TEMPLATE='{http://shema.google.com/codesearch/2006}%s'
29 |
30 |
31 | class Match(atom.AtomBase):
32 | """ The Google Codesearch match element """
33 | _tag = 'match'
34 | _namespace = CODESEARCH_NAMESPACE
35 | _children = atom.AtomBase._children.copy()
36 | _attributes = atom.AtomBase._attributes.copy()
37 | _attributes['lineNumber'] = 'line_number'
38 | _attributes['type'] = 'type'
39 |
40 | def __init__(self, line_number=None, type=None, extension_elements=None,
41 | extension_attributes=None, text=None):
42 | self.text = text
43 | self.type = type
44 | self.line_number = line_number
45 | self.extension_elements = extension_elements or []
46 | self.extension_attributes = extension_attributes or {}
47 |
48 |
49 | class File(atom.AtomBase):
50 | """ The Google Codesearch file element"""
51 | _tag = 'file'
52 | _namespace = CODESEARCH_NAMESPACE
53 | _children = atom.AtomBase._children.copy()
54 | _attributes = atom.AtomBase._attributes.copy()
55 | _attributes['name'] = 'name'
56 |
57 | def __init__(self, name=None, extension_elements=None,
58 | extension_attributes=None, text=None):
59 | self.text = text
60 | self.name = name
61 | self.extension_elements = extension_elements or []
62 | self.extension_attributes = extension_attributes or {}
63 |
64 |
65 | class Package(atom.AtomBase):
66 | """ The Google Codesearch package element"""
67 | _tag = 'package'
68 | _namespace = CODESEARCH_NAMESPACE
69 | _children = atom.AtomBase._children.copy()
70 | _attributes = atom.AtomBase._attributes.copy()
71 | _attributes['name'] = 'name'
72 | _attributes['uri'] = 'uri'
73 |
74 | def __init__(self, name=None, uri=None, extension_elements=None,
75 | extension_attributes=None, text=None):
76 | self.text = text
77 | self.name = name
78 | self.uri = uri
79 | self.extension_elements = extension_elements or []
80 | self.extension_attributes = extension_attributes or {}
81 |
82 |
83 | class CodesearchEntry(gdata.GDataEntry):
84 | """ Google codesearch atom entry"""
85 | _tag = gdata.GDataEntry._tag
86 | _namespace = gdata.GDataEntry._namespace
87 | _children = gdata.GDataEntry._children.copy()
88 | _attributes = gdata.GDataEntry._attributes.copy()
89 |
90 | _children['{%s}file' % CODESEARCH_NAMESPACE] = ('file', File)
91 | _children['{%s}package' % CODESEARCH_NAMESPACE] = ('package', Package)
92 | _children['{%s}match' % CODESEARCH_NAMESPACE] = ('match', [Match])
93 |
94 | def __init__(self, author=None, category=None, content=None,
95 | atom_id=None, link=None, published=None,
96 | title=None, updated=None,
97 | match=None,
98 | extension_elements=None, extension_attributes=None, text=None):
99 |
100 | gdata.GDataEntry.__init__(self, author=author, category=category,
101 | content=content, atom_id=atom_id, link=link,
102 | published=published, title=title,
103 | updated=updated, text=None)
104 |
105 | self.match = match or []
106 |
107 |
108 | def CodesearchEntryFromString(xml_string):
109 | """Converts an XML string into a CodesearchEntry object.
110 |
111 | Args:
112 | xml_string: string The XML describing a Codesearch feed entry.
113 |
114 | Returns:
115 | A CodesearchEntry object corresponding to the given XML.
116 | """
117 | return atom.CreateClassFromXMLString(CodesearchEntry, xml_string)
118 |
119 |
120 | class CodesearchFeed(gdata.GDataFeed):
121 | """feed containing list of Google codesearch Items"""
122 | _tag = gdata.GDataFeed._tag
123 | _namespace = gdata.GDataFeed._namespace
124 | _children = gdata.GDataFeed._children.copy()
125 | _attributes = gdata.GDataFeed._attributes.copy()
126 | _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [CodesearchEntry])
127 |
128 |
129 | def CodesearchFeedFromString(xml_string):
130 | """Converts an XML string into a CodesearchFeed object.
131 | Args:
132 | xml_string: string The XML describing a Codesearch feed.
133 | Returns:
134 | A CodeseartchFeed object corresponding to the given XML.
135 | """
136 | return atom.CreateClassFromXMLString(CodesearchFeed, xml_string)
137 |
--------------------------------------------------------------------------------