Exception
6 years ago
WebAuthException
6 years ago
certs
6 years ago
AppInfo.php
6 years ago
AppInfoLoadException.php
6 years ago
ArrayEntryStore.php
6 years ago
AuthBase.php
6 years ago
AuthInfo.php
6 years ago
AuthInfoLoadException.php
6 years ago
Checker.php
6 years ago
Client.php
6 years ago
Curl.php
6 years ago
CurlStreamRelay.php
6 years ago
DeserializeException.php
6 years ago
DropboxMetadataHeaderCatcher.php
6 years ago
Exception.php
6 years ago
Host.php
6 years ago
HttpResponse.php
6 years ago
OAuth1AccessToken.php
6 years ago
OAuth1Upgrader.php
6 years ago
Path.php
6 years ago
RequestUtil.php
6 years ago
RootCertificates.php
6 years ago
SSLTester.php
6 years ago
Security.php
6 years ago
StreamReadException.php
6 years ago
Util.php
6 years ago
ValueStore.php
6 years ago
WebAuth.php
6 years ago
WebAuthBase.php
6 years ago
WebAuthNoRedirect.php
6 years ago
WriteMode.php
6 years ago
autoload.php
6 years ago
strict.php
6 years ago
RootCertificates.php
145 lines
| 1 | <?php |
| 2 | namespace Dropbox; |
| 3 | |
| 4 | /** |
| 5 | * See: {@link RootCertificates::useExternalPaths()} |
| 6 | */ |
| 7 | class RootCertificates |
| 8 | { |
| 9 | /* @var boolean */ |
| 10 | private static $useExternalFile = false; |
| 11 | |
| 12 | /* @var string[]|null */ |
| 13 | private static $paths = null; // A tuple of (rootCertsFilePath, rootCertsFolderPath) |
| 14 | |
| 15 | /** |
| 16 | * If you're running within a PHAR, call this method before you use the SDK |
| 17 | * to make any network requests. |
| 18 | * |
| 19 | * Normally, the SDK tells cURL to look in the "certs" folder for root certificate |
| 20 | * information. But this won't work if this SDK is running from within a PHAR because |
| 21 | * cURL won't read files that are packaged in a PHAR. |
| 22 | */ |
| 23 | static function useExternalPaths() |
| 24 | { |
| 25 | if (!self::$useExternalFile and self::$paths !== null) { |
| 26 | throw new \Exception("You called \"useExternalFile\" too late. The SDK already used the root ". |
| 27 | "certificate file (probably to make an API call)."); |
| 28 | } |
| 29 | |
| 30 | self::$useExternalFile = true; |
| 31 | } |
| 32 | |
| 33 | private static $originalPath = '/certs/trusted-certs.crt'; |
| 34 | |
| 35 | /** |
| 36 | * @internal |
| 37 | * |
| 38 | * @return string[] |
| 39 | * A tuple of (rootCertsFilePath, rootCertsFolderPath). To be used with cURL options CAINFO and CAPATH. |
| 40 | */ |
| 41 | static function getPaths() |
| 42 | { |
| 43 | if (self::$paths === null) { |
| 44 | if (self::$useExternalFile) { |
| 45 | try { |
| 46 | $baseFolder = sys_get_temp_dir(); |
| 47 | $file = self::createExternalCaFile($baseFolder); |
| 48 | $folder = self::createExternalCaFolder($baseFolder); |
| 49 | } |
| 50 | catch (\Exception $ex) { |
| 51 | throw new \Exception("Unable to create external root certificate file and folder: ".$ex->getMessage()); |
| 52 | } |
| 53 | } |
| 54 | else { |
| 55 | if (substr(__DIR__, 0, 7) === 'phar://') { |
| 56 | throw new \Exception("The code appears to be running in a PHAR. You need to call \\Dropbox\\RootCertificates\\useExternalPaths() before making any API calls."); |
| 57 | } |
| 58 | $file = __DIR__.self::$originalPath; |
| 59 | $folder = \dirname($file); |
| 60 | } |
| 61 | self::$paths = array($file, $folder); |
| 62 | } |
| 63 | |
| 64 | return self::$paths; |
| 65 | } |
| 66 | |
| 67 | /** |
| 68 | * @param string $baseFolder |
| 69 | * |
| 70 | * @return string |
| 71 | */ |
| 72 | private static function createExternalCaFolder($baseFolder) |
| 73 | { |
| 74 | // This is hacky, but I can't find a simple way to do this. |
| 75 | |
| 76 | // This process isn't atomic, so give it three tries. |
| 77 | for ($i = 0; $i < 3; $i++) { |
| 78 | $path = \tempnam($baseFolder, "dropbox-php-sdk-trusted-certs-empty-dir"); |
| 79 | if ($path === false) { |
| 80 | throw new \Exception("Couldn't create temp file in folder ".Util::q($baseFolder)."."); |
| 81 | } |
| 82 | if (!\unlink($path)) { |
| 83 | throw new \Exception("Couldn't remove temp file to make way for temp dir: ".Util::q($path)); |
| 84 | } |
| 85 | // TODO: Figure out how to make the folder private on Windows. The '700' only works on Unix. |
| 86 | if (!\mkdir($path, 700)) { |
| 87 | // Someone snuck in between the unlink() and the mkdir() and stole our path. |
| 88 | throw new \Exception("Couldn't create temp dir: ".Util::q($path)); |
| 89 | } |
| 90 | \register_shutdown_function(function() use ($path) { |
| 91 | \rmdir($path); |
| 92 | }); |
| 93 | return $path; |
| 94 | } |
| 95 | |
| 96 | throw new \Exception("Unable to create temp dir in ".Util::q($baseFolder).", there's always something in the way."); |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * @param string $baseFolder |
| 101 | * |
| 102 | * @return string |
| 103 | */ |
| 104 | private static function createExternalCaFile($baseFolder) |
| 105 | { |
| 106 | $path = \tempnam($baseFolder, "dropbox-php-sdk-trusted-certs"); |
| 107 | if ($path === false) { |
| 108 | throw new \Exception("Couldn't create temp file in folder ".Util::q($baseFolder)."."); |
| 109 | } |
| 110 | \register_shutdown_function(function() use ($path) { |
| 111 | \unlink($path); |
| 112 | }); |
| 113 | |
| 114 | // NOTE: Can't use the standard PHP copy(). That would clobber the locked-down |
| 115 | // permissions set by tempnam(). |
| 116 | self::copyInto(__DIR__.self::$originalPath, $path); |
| 117 | |
| 118 | return $path; |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * @param string $src |
| 123 | * @param string $dest |
| 124 | */ |
| 125 | private static function copyInto($src, $dest) |
| 126 | { |
| 127 | $srcFd = \fopen($src, "r"); |
| 128 | if ($srcFd === false) { |
| 129 | throw new \Exception("Couldn't open " . Util::q($src) . " for reading."); |
| 130 | } |
| 131 | $destFd = \fopen($dest, "w"); |
| 132 | if ($destFd === false) { |
| 133 | \fclose($srcFd); |
| 134 | throw new \Exception("Couldn't open " . Util::q($dest) . " for writing."); |
| 135 | } |
| 136 | |
| 137 | \stream_copy_to_stream($srcFd, $destFd); |
| 138 | |
| 139 | fclose($srcFd); |
| 140 | if (!\fclose($destFd)) { |
| 141 | throw new \Exception("Error closing file ".Util::q($dest)."."); |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 |