2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/stream-wrapper-registry.h"
18 #include "hphp/runtime/base/file.h"
19 #include "hphp/runtime/base/file-stream-wrapper.h"
20 #include "hphp/runtime/base/php-stream-wrapper.h"
21 #include "hphp/runtime/base/http-stream-wrapper.h"
22 #include "hphp/runtime/base/data-stream-wrapper.h"
23 #include "hphp/runtime/base/glob-stream-wrapper.h"
24 #include "hphp/runtime/base/request-local.h"
25 #include "hphp/runtime/base/request-event-handler.h"
26 #include "hphp/runtime/ext/ext_string.h"
32 namespace HPHP
{ namespace Stream
{
33 ///////////////////////////////////////////////////////////////////////////////
36 struct RequestWrappers final
: RequestEventHandler
{
37 void requestInit() override
{}
38 void requestShutdown() override
{
43 std::set
<String
> m_disabled
;
44 std::map
<String
,std::unique_ptr
<Wrapper
>> m_wrappers
;
48 typedef std::map
<std::string
,Wrapper
*> wrapper_map_t
;
50 // Global registry for wrappers
51 static wrapper_map_t s_wrappers
;
53 // Request local registry for user defined wrappers and disabled builtins
54 IMPLEMENT_STATIC_REQUEST_LOCAL(RequestWrappers
, s_request_wrappers
);
56 bool registerWrapper(const std::string
&scheme
, Wrapper
*wrapper
) {
57 assert(s_wrappers
.find(scheme
) == s_wrappers
.end());
58 s_wrappers
[scheme
] = wrapper
;
64 s_compress_zlib("compress.zlib"),
67 bool disableWrapper(const String
& scheme
) {
68 String lscheme
= f_strtolower(scheme
);
70 if (lscheme
.same(s_file
)) {
71 // Zend quietly succeeds, but does nothing
77 // Unregister request-specific wrappers entirely
78 if (s_request_wrappers
->m_wrappers
.find(lscheme
) !=
79 s_request_wrappers
->m_wrappers
.end()) {
80 s_request_wrappers
->m_wrappers
.erase(lscheme
);
84 // Disable builtin wrapper if it exists
85 if (s_wrappers
.find(lscheme
.data()) == s_wrappers
.end()) {
86 // No builtin to disable
90 if (s_request_wrappers
->m_disabled
.find(lscheme
) !=
91 s_request_wrappers
->m_disabled
.end()) {
97 s_request_wrappers
->m_disabled
.insert(lscheme
);
101 bool restoreWrapper(const String
& scheme
) {
102 String lscheme
= f_strtolower(scheme
);
105 // Unregister request-specific wrapper
106 if (s_request_wrappers
->m_wrappers
.find(lscheme
) !=
107 s_request_wrappers
->m_wrappers
.end()) {
108 s_request_wrappers
->m_wrappers
.erase(lscheme
);
112 // Un-disable builtin wrapper
113 if (s_request_wrappers
->m_disabled
.find(lscheme
) ==
114 s_request_wrappers
->m_disabled
.end()) {
119 // Perform action un-disable
120 s_request_wrappers
->m_disabled
.erase(lscheme
);
124 bool registerRequestWrapper(const String
& scheme
,
125 std::unique_ptr
<Wrapper
> wrapper
) {
126 String lscheme
= f_strtolower(scheme
);
128 // Global, non-disabled wrapper
129 if ((s_wrappers
.find(lscheme
.data()) != s_wrappers
.end()) &&
130 (s_request_wrappers
->m_disabled
.find(lscheme
) ==
131 s_request_wrappers
->m_disabled
.end())) {
135 // A wrapper has already been registered for that scheme
136 if (s_request_wrappers
->m_wrappers
.find(lscheme
) !=
137 s_request_wrappers
->m_wrappers
.end()) {
141 s_request_wrappers
->m_wrappers
[lscheme
] = std::move(wrapper
);
145 Array
enumWrappers() {
146 Array ret
= Array::Create();
148 // Enum global wrappers which are not disabled
149 for (auto it
= s_wrappers
.begin(); it
!= s_wrappers
.end(); ++it
) {
150 if (s_request_wrappers
->m_disabled
.find(it
->first
) ==
151 s_request_wrappers
->m_disabled
.end()) {
152 ret
.append(it
->first
);
156 // Enum request local wrappers
157 for (auto it
= s_request_wrappers
->m_wrappers
.begin();
158 it
!= s_request_wrappers
->m_wrappers
.end(); ++it
) {
159 ret
.append(it
->first
);
164 Wrapper
* getWrapper(const String
& scheme
) {
165 String lscheme
= f_strtolower(scheme
);
167 // Request local wrapper?
169 auto it
= s_request_wrappers
->m_wrappers
.find(lscheme
);
170 if (it
!= s_request_wrappers
->m_wrappers
.end()) {
171 return it
->second
.get();
175 // Global, non-disabled wrapper?
177 auto it
= s_wrappers
.find(lscheme
.data());
178 if ((it
!= s_wrappers
.end()) &&
179 (s_request_wrappers
->m_disabled
.find(lscheme
) ==
180 s_request_wrappers
->m_disabled
.end())) {
188 Wrapper
* getWrapperFromURI(const String
& uri
, int* pathIndex
/* = NULL */) {
189 const char *uri_string
= uri
.data();
191 /* Special case for PHP4 Backward Compatability */
192 if (!strncasecmp(uri_string
, "zlib:", sizeof("zlib:") - 1)) {
193 return getWrapper(s_compress_zlib
);
196 // data wrapper can come with or without a double forward slash
197 if (!strncasecmp(uri_string
, "data:", sizeof("data:") - 1)) {
198 return getWrapper(s_data
);
201 const char *colon
= strstr(uri_string
, "://");
203 return getWrapper(s_file
);
206 int len
= colon
- uri_string
;
207 if (pathIndex
!= nullptr) *pathIndex
= len
+ sizeof("://") - 1;
208 if (Wrapper
*w
= getWrapper(String(uri_string
, len
, CopyString
))) {
211 return getWrapper(s_file
);
214 static FileStreamWrapper s_file_stream_wrapper
;
215 static PhpStreamWrapper s_php_stream_wrapper
;
216 static HttpStreamWrapper s_http_stream_wrapper
;
217 static DataStreamWrapper s_data_stream_wrapper
;
218 static GlobStreamWrapper s_glob_stream_wrapper
;
220 void RegisterCoreWrappers() {
221 s_file_stream_wrapper
.registerAs("file");
222 s_php_stream_wrapper
.registerAs("php");
223 s_http_stream_wrapper
.registerAs("http");
224 s_http_stream_wrapper
.registerAs("https");
225 s_data_stream_wrapper
.registerAs("data");
226 s_glob_stream_wrapper
.registerAs("glob");
229 ///////////////////////////////////////////////////////////////////////////////