PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/3.0/Source/ExtSupport/StreamProxy.h

#
C++ Header | 308 lines | 115 code | 51 blank | 142 comment | 4 complexity | 9464399872028020f52f7d12b401be5c MD5 | raw file
Possible License(s): CPL-1.0, GPL-2.0, CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. //
  2. // ExtSupport - substitute for php4ts.dll/php5ts.dll
  3. //
  4. // StreamProxy.h
  5. // - contains declaration of StreamWrapperProxy class
  6. // - contains declaration of StreamProxy class
  7. //
  8. #pragma once
  9. #include "stdafx.h"
  10. #include "Streams.h"
  11. #include "Request.h"
  12. #include "Module.h"
  13. #undef RemoveDirectory // grrr...
  14. using namespace System;
  15. using namespace System::IO;
  16. using namespace PHP::Core;
  17. /*
  18. Designed and implemented by Ladislav Prosek.
  19. */
  20. namespace PHP
  21. {
  22. namespace ExtManager
  23. {
  24. /// <summary>
  25. /// Class of remotable, marshaled by reference objects that serve as proxies of native PHP stream wrappers.
  26. /// </summary>
  27. private ref class StreamWrapperProxy : public MarshalByRefObject, public ISponsor, public ILifetimeBoundMBR,
  28. public IExternalStreamWrapper
  29. {
  30. private:
  31. /// <summary>
  32. /// Creates a new <see cref="StreamWrapperProxy"/>.
  33. /// </summary>
  34. /// <param name="wrapper">The underlying native PHP stream wrapper.</param>
  35. /// <remarks>
  36. /// This constructor is private. Use <see cref="CreateWrapperProxy"/> factory method to
  37. /// obtain an instance.
  38. /// </remarks>
  39. StreamWrapperProxy(php_stream_wrapper *wrapper, Module ^containingModule)
  40. {
  41. this->wrapper = wrapper;
  42. this->containingModule = containingModule;
  43. this->isExpired = false;
  44. Request::GetCurrentRequest()->RegisterLifetimeBoundMBR(this);
  45. }
  46. /// <summary>Pointer to the underlying native PHP stream wrapper.</summary>
  47. php_stream_wrapper *wrapper;
  48. /// <summary>The <see cref="Module"/> that registered this stream wrapper.</summary>
  49. Module ^containingModule;
  50. /// <summary>
  51. /// <B>true</B> if this instance has expired and should no longer be retained, <B>false</B>
  52. /// otherwise.
  53. /// </summary>
  54. bool isExpired;
  55. public:
  56. /// <summary>
  57. /// Obtains a lifetime service object to control the lifetime policy for this instance.
  58. /// </summary>
  59. /// <returns>An object of type <see cref="ILease"/> used to control the lifetime policy for this
  60. /// instance.</returns>
  61. /// <remarks>
  62. /// <see cref="MarshalByRefObject.InitializeLifetimeService"/> is overriden in order to be able to
  63. /// register a sponsor. This very object becomes its own sponsor. <seealso cref="ISponsor"/>
  64. /// </remarks>
  65. virtual Object ^InitializeLifetimeService() override
  66. {
  67. ILease ^lease = static_cast<ILease ^>(MarshalByRefObject::InitializeLifetimeService());
  68. lease->Register(this);
  69. return lease;
  70. }
  71. // ISponsor implementation
  72. /// <summary>
  73. /// Requests a sponsoring client to renew the lease for this object.
  74. /// </summary>
  75. /// <param name="lease">The lifetime lease of the object that requires lease renewal.</param>
  76. /// <returns>The additional lease time for the specified object.</returns>
  77. virtual TimeSpan Renewal(ILease ^lease)
  78. {
  79. #ifdef DEBUG
  80. Debug::WriteLine("EXT SUP", "StreamWrapperProxy::Renewal");
  81. #endif
  82. if (isExpired) return TimeSpan::Zero;
  83. else return lease->RenewOnCallTime;
  84. }
  85. // ILifetimeBoundMBR implementation
  86. // Invoked by the <see cref="Request"/> this instance is bound to, to signalize that
  87. // the lifetime expires.
  88. virtual void Expire()
  89. {
  90. isExpired = true;
  91. }
  92. // IExternalStreamWrapper implementation
  93. /// <summary>
  94. /// Returns an <see cref="IExternalStream"/> proxy of a native PHP stream.
  95. /// </summary>
  96. /// <param name="path">The file path passed to <c>fopen</c> PHP function.</param>
  97. /// <param name="mode">The mode passed to <c>fopen</c> PHP function.</param>
  98. /// <param name="options">Combination of <c>StreamWrapper.StreamOpenFlags</c>.</param>
  99. /// <param name="opened_path">The real full path of the file actually opened.</param>
  100. /// <param name="context">The context provided for the stream wrapper at the call to <c>fopen</c>
  101. /// PHP function.</param>
  102. /// <returns>
  103. /// A new <see cref="MarshalByRefObject"/> implementing the <see cref="IExternalStream"/> interface
  104. /// or <B>null</B> if there was an error.
  105. /// </returns>
  106. virtual IExternalStream ^Open(String ^path, String ^mode, int options, String ^%opened_path,
  107. Object ^context);
  108. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="Stat"]/*'/>
  109. virtual StatStruct Stat(String ^path, int options, Object ^context, bool streamStat);
  110. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="Unlink"]/*'/>
  111. virtual bool Unlink(String ^path, int options, Object ^context);
  112. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="Listing"]/*'/>
  113. virtual array<String ^> ^Listing(String ^path, int options, Object ^context);
  114. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="Rename"]/*'/>
  115. virtual bool Rename(String ^fromPath, String ^toPath, int options, Object ^context);
  116. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="MakeDirectory"]/*'/>
  117. virtual bool MakeDirectory(String ^path, int accessMode, int options, Object ^context);
  118. /// <include file='../Core/Doc/Wrappers.xml' path='docs/method[@name="RemoveDirectory"]/*'/>
  119. virtual bool RemoveDirectory(String ^path, int options, Object ^context);
  120. /// <include file='../Core/Doc/Wrappers.xml' path='docs/property[@name="Label"]/*'/>
  121. virtual property String ^Label
  122. {
  123. String ^get();
  124. }
  125. /// <include file='../Core/Doc/Wrappers.xml' path='docs/property[@name="IsUrl"]/*'/>
  126. virtual property bool IsUrl
  127. {
  128. bool get();
  129. }
  130. public:
  131. /// <summary>
  132. /// Creates a new <see cref="StreamWrapperProxy"/> for the given scheme portion of a URL.
  133. /// </summary>
  134. /// <param name="scheme">The scheme for which a wrapper is requested.</param>
  135. /// <returns>The <see cref="StreamWrapperProxy"/> or <B>null</B> if no wrapper was found for the
  136. /// given scheme.</returns>
  137. static StreamWrapperProxy ^CreateWrapperProxy(String ^scheme);
  138. /// <summary>
  139. /// Returns an <see cref="ICollection"/> of schemes of all registered stream wrappers.
  140. /// </summary>
  141. /// <returns>The <see cref="ICollection"/>.</returns>
  142. static ICollection ^GetWrapperSchemes();
  143. /// <summary>
  144. /// Updates <see cref="streamWrapperModules"/>.
  145. /// </summary>
  146. /// <param name="scheme">The scheme of the wrapper being registered.</param>
  147. static void RegisterWrapper(String ^scheme);
  148. /// <summary>
  149. /// Updates <see cref="streamWrapperModules"/>.
  150. /// </summary>
  151. /// <param name="scheme">The scheme of the wrapper being unregistered.</param>
  152. static void UnregisterWrapper(String ^scheme);
  153. private:
  154. /// <summary>
  155. /// Keys are wrapper schemes, values are <see cref="Module"/>s that registered the wrapper.
  156. /// </summary>
  157. static Hashtable ^streamWrapperModules = gcnew Hashtable();
  158. };
  159. /// <summary>
  160. /// Class of remotable, marshaled by reference objects that serve as proxies of native PHP stream.
  161. /// </summary>
  162. private ref class StreamProxy : public MarshalByRefObject, public ISponsor, public ILifetimeBoundMBR,
  163. public IExternalStream
  164. {
  165. public:
  166. /// <summary>
  167. /// Creates a new <see cref="StreamProxy"/>.
  168. /// </summary>
  169. /// <param name="stream">The underlying native PHP stream.</param>
  170. /// <remarks>
  171. /// Use <see cref="StreamWrapperProxy.Open"/> factory method to obtain an instance.
  172. /// </remarks>
  173. StreamProxy(php_stream *stream, Module ^containingModule)
  174. {
  175. this->stream = stream;
  176. this->containingModule = containingModule;
  177. this->isExpired = false;
  178. Request::GetCurrentRequest()->RegisterLifetimeBoundMBR(this);
  179. }
  180. /// <summary>
  181. /// Obtains a lifetime service object to control the lifetime policy for this instance.
  182. /// </summary>
  183. /// <returns>An object of type <see cref="ILease"/> used to control the lifetime policy for this
  184. /// instance.</returns>
  185. /// <remarks>
  186. /// <see cref="MarshalByRefObject.InitializeLifetimeService"/> is overriden in order to be able to
  187. /// register a sponsor. This very object becomes its own sponsor. <seealso cref="ISponsor"/>
  188. /// </remarks>
  189. virtual Object ^InitializeLifetimeService() override
  190. {
  191. ILease ^lease = static_cast<ILease ^>(MarshalByRefObject::InitializeLifetimeService());
  192. lease->Register(this);
  193. return lease;
  194. }
  195. // ISponsor implementation
  196. /// <summary>
  197. /// Requests a sponsoring client to renew the lease for this object.
  198. /// </summary>
  199. /// <param name="lease">The lifetime lease of the object that requires lease renewal.</param>
  200. /// <returns>The additional lease time for the specified object.</returns>
  201. virtual TimeSpan Renewal(ILease ^lease)
  202. {
  203. #ifdef DEBUG
  204. Debug::WriteLine("EXT SUP", "StreamProxy::Renewal");
  205. #endif
  206. if (isExpired) return TimeSpan::Zero;
  207. else return lease->RenewOnCallTime;
  208. }
  209. // ILifetimeBoundMBR implementation
  210. // Invoked by the <see cref="Request"/> this instance is bound to, to signalize that
  211. // the lifetime expires.
  212. virtual void Expire()
  213. {
  214. Close();
  215. isExpired = true;
  216. }
  217. // IExternalStream implementation
  218. /// <include file='../ClassLibrary/Doc/Streams.xml' path='/docs/method[@name="RawWrite"]/*'/>
  219. virtual int Write(array<unsigned char> ^buffer, int offset, int count);
  220. /// <include file='../ClassLibrary/Doc/Streams.xml' path='/docs/method[@name="RawRead"]/*'/>
  221. virtual int Read(array<unsigned char> ^%buffer, int offset, int count);
  222. /// <summary>
  223. /// Closes the stream.
  224. /// </summary>
  225. /// <returns><B>true</B> on success, <B>false</B> on error.</returns>
  226. virtual bool Close();
  227. /// <include file='../ClassLibrary/Doc/Streams.xml' path='/docs/method[@name="RawFlush"]/*'/>
  228. virtual bool Flush();
  229. /// <include file='../ClassLibrary/Doc/Streams.xml' path=/docs/method[@name="RawSeek"]/*'/>
  230. virtual bool Seek(int offset, SeekOrigin whence);
  231. /// <summary>
  232. /// Gets the current position in the stream.
  233. /// </summary>
  234. /// <returns>The position or <c>-1</c> on error.</returns>
  235. virtual int Tell();
  236. /// <include file='../ClassLibrary/Doc/Streams.xml' path='/docs/property[@name="Eof"]/*'/>
  237. virtual bool Eof();
  238. /// <summary>
  239. /// Returns the stat structure for the stram.
  240. /// </summary>
  241. /// <returns>The stat structure describing the stream.</returns>
  242. virtual StatStruct Stat();
  243. private:
  244. /// <summary>Pointer to the underlying native PHP stream.</summary>
  245. php_stream *stream;
  246. /// <summary>The <see cref="Module"/> that registered the corresponding stream wrapper.</summary>
  247. Module ^containingModule;
  248. /// <summary>
  249. /// <B>true</B> if this instance has expired and should no longer be retained, <B>false</B>
  250. /// otherwise.
  251. /// </summary>
  252. bool isExpired;
  253. };
  254. }
  255. }