| OLD | NEW | 
|---|
| 1 # Copyright (C) 2010 Google Inc. | 1 # Copyright 2014 Google Inc. All rights reserved. | 
| 2 # | 2 # | 
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. | 
| 5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at | 
| 6 # | 6 # | 
| 7 #      http://www.apache.org/licenses/LICENSE-2.0 | 7 #      http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 # | 8 # | 
| 9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software | 
| 10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, | 
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 12 # See the License for the specific language governing permissions and | 12 # See the License for the specific language governing permissions and | 
| 13 # limitations under the License. | 13 # limitations under the License. | 
| 14 | 14 | 
| 15 """Utilities for OAuth. | 15 """Utilities for OAuth. | 
| 16 | 16 | 
| 17 Utilities for making it easier to work with OAuth 2.0 | 17 Utilities for making it easier to work with OAuth 2.0 | 
| 18 credentials. | 18 credentials. | 
| 19 """ | 19 """ | 
| 20 | 20 | 
| 21 __author__ = 'jcgregorio@google.com (Joe Gregorio)' | 21 __author__ = 'jcgregorio@google.com (Joe Gregorio)' | 
| 22 | 22 | 
| 23 import os | 23 import os | 
| 24 import stat |  | 
| 25 import threading | 24 import threading | 
| 26 | 25 | 
| 27 from anyjson import simplejson | 26 from oauth2client.client import Credentials | 
| 28 from client import Storage as BaseStorage | 27 from oauth2client.client import Storage as BaseStorage | 
| 29 from client import Credentials | 28 | 
|  | 29 | 
|  | 30 class CredentialsFileSymbolicLinkError(Exception): | 
|  | 31   """Credentials files must not be symbolic links.""" | 
| 30 | 32 | 
| 31 | 33 | 
| 32 class Storage(BaseStorage): | 34 class Storage(BaseStorage): | 
| 33   """Store and retrieve a single credential to and from a file.""" | 35   """Store and retrieve a single credential to and from a file.""" | 
| 34 | 36 | 
| 35   def __init__(self, filename): | 37   def __init__(self, filename): | 
| 36     self._filename = filename | 38     self._filename = filename | 
| 37     self._lock = threading.Lock() | 39     self._lock = threading.Lock() | 
| 38 | 40 | 
|  | 41   def _validate_file(self): | 
|  | 42     if os.path.islink(self._filename): | 
|  | 43       raise CredentialsFileSymbolicLinkError( | 
|  | 44           'File: %s is a symbolic link.' % self._filename) | 
|  | 45 | 
| 39   def acquire_lock(self): | 46   def acquire_lock(self): | 
| 40     """Acquires any lock necessary to access this Storage. | 47     """Acquires any lock necessary to access this Storage. | 
| 41 | 48 | 
| 42     This lock is not reentrant.""" | 49     This lock is not reentrant.""" | 
| 43     self._lock.acquire() | 50     self._lock.acquire() | 
| 44 | 51 | 
| 45   def release_lock(self): | 52   def release_lock(self): | 
| 46     """Release the Storage lock. | 53     """Release the Storage lock. | 
| 47 | 54 | 
| 48     Trying to release a lock that isn't held will result in a | 55     Trying to release a lock that isn't held will result in a | 
| 49     RuntimeError. | 56     RuntimeError. | 
| 50     """ | 57     """ | 
| 51     self._lock.release() | 58     self._lock.release() | 
| 52 | 59 | 
| 53   def locked_get(self): | 60   def locked_get(self): | 
| 54     """Retrieve Credential from file. | 61     """Retrieve Credential from file. | 
| 55 | 62 | 
| 56     Returns: | 63     Returns: | 
| 57       oauth2client.client.Credentials | 64       oauth2client.client.Credentials | 
|  | 65 | 
|  | 66     Raises: | 
|  | 67       CredentialsFileSymbolicLinkError if the file is a symbolic link. | 
| 58     """ | 68     """ | 
| 59     credentials = None | 69     credentials = None | 
|  | 70     self._validate_file() | 
| 60     try: | 71     try: | 
| 61       f = open(self._filename, 'rb') | 72       f = open(self._filename, 'rb') | 
| 62       content = f.read() | 73       content = f.read() | 
| 63       f.close() | 74       f.close() | 
| 64     except IOError: | 75     except IOError: | 
| 65       return credentials | 76       return credentials | 
| 66 | 77 | 
| 67     try: | 78     try: | 
| 68       credentials = Credentials.new_from_json(content) | 79       credentials = Credentials.new_from_json(content) | 
| 69       credentials.set_store(self) | 80       credentials.set_store(self) | 
| 70     except ValueError: | 81     except ValueError: | 
| 71       pass | 82       pass | 
| 72 | 83 | 
| 73     return credentials | 84     return credentials | 
| 74 | 85 | 
| 75   def _create_file_if_needed(self): | 86   def _create_file_if_needed(self): | 
| 76     """Create an empty file if necessary. | 87     """Create an empty file if necessary. | 
| 77 | 88 | 
| 78     This method will not initialize the file. Instead it implements a | 89     This method will not initialize the file. Instead it implements a | 
| 79     simple version of "touch" to ensure the file has been created. | 90     simple version of "touch" to ensure the file has been created. | 
| 80     """ | 91     """ | 
| 81     if not os.path.exists(self._filename): | 92     if not os.path.exists(self._filename): | 
| 82       old_umask = os.umask(0177) | 93       old_umask = os.umask(0o177) | 
| 83       try: | 94       try: | 
| 84         open(self._filename, 'a+b').close() | 95         open(self._filename, 'a+b').close() | 
| 85       finally: | 96       finally: | 
| 86         os.umask(old_umask) | 97         os.umask(old_umask) | 
| 87 | 98 | 
| 88 |  | 
| 89   def locked_put(self, credentials): | 99   def locked_put(self, credentials): | 
| 90     """Write Credentials to file. | 100     """Write Credentials to file. | 
| 91 | 101 | 
| 92     Args: | 102     Args: | 
| 93       credentials: Credentials, the credentials to store. | 103       credentials: Credentials, the credentials to store. | 
|  | 104 | 
|  | 105     Raises: | 
|  | 106       CredentialsFileSymbolicLinkError if the file is a symbolic link. | 
| 94     """ | 107     """ | 
| 95 | 108 | 
| 96     self._create_file_if_needed() | 109     self._create_file_if_needed() | 
| 97     f = open(self._filename, 'wb') | 110     self._validate_file() | 
|  | 111     f = open(self._filename, 'w') | 
| 98     f.write(credentials.to_json()) | 112     f.write(credentials.to_json()) | 
| 99     f.close() | 113     f.close() | 
|  | 114 | 
|  | 115   def locked_delete(self): | 
|  | 116     """Delete Credentials file. | 
|  | 117 | 
|  | 118     Args: | 
|  | 119       credentials: Credentials, the credentials to store. | 
|  | 120     """ | 
|  | 121 | 
|  | 122     os.unlink(self._filename) | 
| OLD | NEW | 
|---|