PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/_octopress/source/functions/file_get_contents/index.markdown

https://gitlab.com/orvi2014/phpjs
Markdown | 301 lines | 278 code | 23 blank | 0 comment | 0 complexity | 94508b18fb92e4822cee63365af7d4c8 MD5 | raw file
  1. ---
  2. layout: page
  3. title: "JavaScript file_get_contents function"
  4. comments: true
  5. sharing: true
  6. footer: true
  7. alias:
  8. - /functions/view/file_get_contents:400
  9. - /functions/view/file_get_contents
  10. - /functions/view/400
  11. - /functions/file_get_contents:400
  12. - /functions/400
  13. ---
  14. <!-- Generated by Rakefile:build -->
  15. A JavaScript equivalent of PHP's file_get_contents
  16. {% codeblock filesystem/file_get_contents.js lang:js https://raw.github.com/kvz/phpjs/master/functions/filesystem/file_get_contents.js raw on github %}
  17. function file_get_contents(url, flags, context, offset, maxLen) {
  18. // discuss at: http://phpjs.org/functions/file_get_contents/
  19. // original by: Legaev Andrey
  20. // input by: Jani Hartikainen
  21. // input by: Raphael (Ao) RUDLER
  22. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  23. // improved by: Brett Zamir (http://brett-zamir.me)
  24. // bugfixed by: Brett Zamir (http://brett-zamir.me)
  25. // note: This function uses XmlHttpRequest and cannot retrieve resource from different domain without modifications.
  26. // note: Synchronous by default (as in PHP) so may lock up browser. Can
  27. // note: get async by setting a custom "phpjs.async" property to true and "notification" for an
  28. // note: optional callback (both as context params, with responseText, and other JS-specific
  29. // note: request properties available via 'this'). Note that file_get_contents() will not return the text
  30. // note: in such a case (use this.responseText within the callback). Or, consider using
  31. // note: jQuery's: $('#divId').load('http://url') instead.
  32. // note: The context argument is only implemented for http, and only partially (see below for
  33. // note: "Presently unimplemented HTTP context options"); also the arguments passed to
  34. // note: notification are incomplete
  35. // test: skip
  36. // example 1: var buf file_get_contents('http://google.com');
  37. // example 1: buf.indexOf('Google') !== -1
  38. // returns 1: true
  39. var tmp, headers = [],
  40. newTmp = [],
  41. k = 0,
  42. i = 0,
  43. href = '',
  44. pathPos = -1,
  45. flagNames = 0,
  46. content = null,
  47. http_stream = false;
  48. var func = function(value) {
  49. return value.substring(1) !== '';
  50. };
  51. // BEGIN REDUNDANT
  52. this.php_js = this.php_js || {};
  53. this.php_js.ini = this.php_js.ini || {};
  54. // END REDUNDANT
  55. var ini = this.php_js.ini;
  56. context = context || this.php_js.default_streams_context || null;
  57. if (!flags) {
  58. flags = 0;
  59. }
  60. var OPTS = {
  61. FILE_USE_INCLUDE_PATH: 1,
  62. FILE_TEXT: 32,
  63. FILE_BINARY: 64
  64. };
  65. if (typeof flags === 'number') { // Allow for a single string or an array of string flags
  66. flagNames = flags;
  67. } else {
  68. flags = [].concat(flags);
  69. for (i = 0; i < flags.length; i++) {
  70. if (OPTS[flags[i]]) {
  71. flagNames = flagNames | OPTS[flags[i]];
  72. }
  73. }
  74. }
  75. if (flagNames & OPTS.FILE_BINARY && (flagNames & OPTS.FILE_TEXT)) { // These flags shouldn't be together
  76. throw 'You cannot pass both FILE_BINARY and FILE_TEXT to file_get_contents()';
  77. }
  78. if ((flagNames & OPTS.FILE_USE_INCLUDE_PATH) && ini.include_path && ini.include_path.local_value) {
  79. var slash = ini.include_path.local_value.indexOf('/') !== -1 ? '/' : '\\';
  80. url = ini.include_path.local_value + slash + url;
  81. } else if (!/^(https?|file):/.test(url)) { // Allow references within or below the same directory (should fix to allow other relative references or root reference; could make dependent on parse_url())
  82. href = this.window.location.href;
  83. pathPos = url.indexOf('/') === 0 ? href.indexOf('/', 8) - 1 : href.lastIndexOf('/');
  84. url = href.slice(0, pathPos + 1) + url;
  85. }
  86. var http_options;
  87. if (context) {
  88. http_options = context.stream_options && context.stream_options.http;
  89. http_stream = !! http_options;
  90. }
  91. if (!context || http_stream) {
  92. var req = this.window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
  93. if (!req) {
  94. throw new Error('XMLHttpRequest not supported');
  95. }
  96. var method = http_stream ? http_options.method : 'GET';
  97. var async = !! (context && context.stream_params && context.stream_params['phpjs.async']);
  98. if (ini['phpjs.ajaxBypassCache'] && ini['phpjs.ajaxBypassCache'].local_value) {
  99. url += (url.match(/\?/) == null ? '?' : '&') + (new Date())
  100. .getTime(); // Give optional means of forcing bypass of cache
  101. }
  102. req.open(method, url, async);
  103. if (async) {
  104. var notification = context.stream_params.notification;
  105. if (typeof notification === 'function') {
  106. // Fix: make work with req.addEventListener if available: https://developer.mozilla.org/En/Using_XMLHttpRequest
  107. if (0 && req.addEventListener) { // Unimplemented so don't allow to get here
  108. /*
  109. req.addEventListener('progress', updateProgress, false);
  110. req.addEventListener('load', transferComplete, false);
  111. req.addEventListener('error', transferFailed, false);
  112. req.addEventListener('abort', transferCanceled, false);
  113. */
  114. } else {
  115. req.onreadystatechange = function(aEvt) { // aEvt has stopPropagation(), preventDefault(); see https://developer.mozilla.org/en/NsIDOMEvent
  116. // Other XMLHttpRequest properties: multipart, responseXML, status, statusText, upload, withCredentials
  117. /*
  118. PHP Constants:
  119. STREAM_NOTIFY_RESOLVE 1 A remote address required for this stream has been resolved, or the resolution failed. See severity for an indication of which happened.
  120. STREAM_NOTIFY_CONNECT 2 A connection with an external resource has been established.
  121. STREAM_NOTIFY_AUTH_REQUIRED 3 Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR.
  122. STREAM_NOTIFY_MIME_TYPE_IS 4 The mime-type of resource has been identified, refer to message for a description of the discovered type.
  123. STREAM_NOTIFY_FILE_SIZE_IS 5 The size of the resource has been discovered.
  124. STREAM_NOTIFY_REDIRECTED 6 The external resource has redirected the stream to an alternate location. Refer to message .
  125. STREAM_NOTIFY_PROGRESS 7 Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
  126. STREAM_NOTIFY_COMPLETED 8 There is no more data available on the stream.
  127. STREAM_NOTIFY_FAILURE 9 A generic error occurred on the stream, consult message and message_code for details.
  128. STREAM_NOTIFY_AUTH_RESULT 10 Authorization has been completed (with or without success).
  129. STREAM_NOTIFY_SEVERITY_INFO 0 Normal, non-error related, notification.
  130. STREAM_NOTIFY_SEVERITY_WARN 1 Non critical error condition. Processing may continue.
  131. STREAM_NOTIFY_SEVERITY_ERR 2 A critical error occurred. Processing cannot continue.
  132. */
  133. var objContext = {
  134. responseText: req.responseText,
  135. responseXML: req.responseXML,
  136. status: req.status,
  137. statusText: req.statusText,
  138. readyState: req.readyState,
  139. evt: aEvt
  140. }; // properties are not available in PHP, but offered on notification via 'this' for convenience
  141. // notification args: notification_code, severity, message, message_code, bytes_transferred, bytes_max (all int's except string 'message')
  142. // Need to add message, etc.
  143. var bytes_transferred;
  144. switch (req.readyState) {
  145. case 0:
  146. // UNINITIALIZED open() has not been called yet.
  147. notification.call(objContext, 0, 0, '', 0, 0, 0);
  148. break;
  149. case 1:
  150. // LOADING send() has not been called yet.
  151. notification.call(objContext, 0, 0, '', 0, 0, 0);
  152. break;
  153. case 2:
  154. // LOADED send() has been called, and headers and status are available.
  155. notification.call(objContext, 0, 0, '', 0, 0, 0);
  156. break;
  157. case 3:
  158. // INTERACTIVE Downloading; responseText holds partial data.
  159. bytes_transferred = req.responseText.length * 2; // One character is two bytes
  160. notification.call(objContext, 7, 0, '', 0, bytes_transferred, 0);
  161. break;
  162. case 4:
  163. // COMPLETED The operation is complete.
  164. if (req.status >= 200 && req.status < 400) {
  165. bytes_transferred = req.responseText.length * 2; // One character is two bytes
  166. notification.call(objContext, 8, 0, '', req.status, bytes_transferred, 0);
  167. } else if (req.status === 403) { // Fix: These two are finished except for message
  168. notification.call(objContext, 10, 2, '', req.status, 0, 0);
  169. } else { // Errors
  170. notification.call(objContext, 9, 2, '', req.status, 0, 0);
  171. }
  172. break;
  173. default:
  174. throw 'Unrecognized ready state for file_get_contents()';
  175. }
  176. };
  177. }
  178. }
  179. }
  180. if (http_stream) {
  181. var sendHeaders = http_options.header && http_options.header.split(/\r?\n/);
  182. var userAgentSent = false;
  183. for (i = 0; i < sendHeaders.length; i++) {
  184. var sendHeader = sendHeaders[i];
  185. var breakPos = sendHeader.search(/:\s*/);
  186. var sendHeaderName = sendHeader.substring(0, breakPos);
  187. req.setRequestHeader(sendHeaderName, sendHeader.substring(breakPos + 1));
  188. if (sendHeaderName === 'User-Agent') {
  189. userAgentSent = true;
  190. }
  191. }
  192. if (!userAgentSent) {
  193. var user_agent = http_options.user_agent || (ini.user_agent && ini.user_agent.local_value);
  194. if (user_agent) {
  195. req.setRequestHeader('User-Agent', user_agent);
  196. }
  197. }
  198. content = http_options.content || null;
  199. /*
  200. // Presently unimplemented HTTP context options
  201. var request_fulluri = http_options.request_fulluri || false; // When set to TRUE, the entire URI will be used when constructing the request. (i.e. GET http://www.example.com/path/to/file.html HTTP/1.0). While this is a non-standard request format, some proxy servers require it.
  202. var max_redirects = http_options.max_redirects || 20; // The max number of redirects to follow. Value 1 or less means that no redirects are followed.
  203. var protocol_version = http_options.protocol_version || 1.0; // HTTP protocol version
  204. var timeout = http_options.timeout || (ini.default_socket_timeout && ini.default_socket_timeout.local_value); // Read timeout in seconds, specified by a float
  205. var ignore_errors = http_options.ignore_errors || false; // Fetch the content even on failure status codes.
  206. */
  207. }
  208. if (flagNames & OPTS.FILE_TEXT) { // Overrides how encoding is treated (regardless of what is returned from the server)
  209. var content_type = 'text/html';
  210. if (http_options && http_options['phpjs.override']) { // Fix: Could allow for non-HTTP as well
  211. content_type = http_options['phpjs.override']; // We use this, e.g., in gettext-related functions if character set
  212. // overridden earlier by bind_textdomain_codeset()
  213. } else {
  214. var encoding = (ini['unicode.stream_encoding'] && ini['unicode.stream_encoding'].local_value) ||
  215. 'UTF-8';
  216. if (http_options && http_options.header && (/^content-type:/im)
  217. .test(http_options.header)) { // We'll assume a content-type expects its own specified encoding if present
  218. content_type = http_options.header.match(/^content-type:\s*(.*)$/im)[1]; // We let any header encoding stand
  219. }
  220. if (!(/;\s*charset=/)
  221. .test(content_type)) { // If no encoding
  222. content_type += '; charset=' + encoding;
  223. }
  224. }
  225. req.overrideMimeType(content_type);
  226. }
  227. // Default is FILE_BINARY, but for binary, we apparently deviate from PHP in requiring the flag, since many if not
  228. // most people will also want a way to have it be auto-converted into native JavaScript text instead
  229. else if (flagNames & OPTS.FILE_BINARY) { // Trick at https://developer.mozilla.org/En/Using_XMLHttpRequest to get binary
  230. req.overrideMimeType('text/plain; charset=x-user-defined');
  231. // Getting an individual byte then requires:
  232. // responseText.charCodeAt(x) & 0xFF; // throw away high-order byte (f7) where x is 0 to responseText.length-1 (see notes in our substr())
  233. }
  234. try {
  235. if (http_options && http_options['phpjs.sendAsBinary']) { // For content sent in a POST or PUT request (use with file_put_contents()?)
  236. req.sendAsBinary(content); // In Firefox, only available FF3+
  237. } else {
  238. req.send(content);
  239. }
  240. } catch (e) {
  241. // catches exception reported in issue #66
  242. return false;
  243. }
  244. tmp = req.getAllResponseHeaders();
  245. if (tmp) {
  246. tmp = tmp.split('\n');
  247. for (k = 0; k < tmp.length; k++) {
  248. if (func(tmp[k])) {
  249. newTmp.push(tmp[k]);
  250. }
  251. }
  252. tmp = newTmp;
  253. for (i = 0; i < tmp.length; i++) {
  254. headers[i] = tmp[i];
  255. }
  256. this.$http_response_header = headers; // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
  257. }
  258. if (offset || maxLen) {
  259. if (maxLen) {
  260. return req.responseText.substr(offset || 0, maxLen);
  261. }
  262. return req.responseText.substr(offset);
  263. }
  264. return req.responseText;
  265. }
  266. return false;
  267. }
  268. {% endcodeblock %}
  269. - [Raw function on GitHub](https://github.com/kvz/phpjs/blob/master/functions/filesystem/file_get_contents.js)
  270. Please note that php.js uses JavaScript objects as substitutes for PHP arrays, they are
  271. the closest match to this hashtable-like data structure.
  272. Please also note that php.js offers community built functions and goes by the
  273. [McDonald's Theory](https://medium.com/what-i-learned-building/9216e1c9da7d). We'll put online
  274. functions that are far from perfect, in the hopes to spark better contributions.
  275. Do you have one? Then please just:
  276. - [Edit on GitHub](https://github.com/kvz/phpjs/edit/master/functions/filesystem/file_get_contents.js)
  277. ### Other PHP functions in the filesystem extension
  278. {% render_partial _includes/custom/filesystem.html %}