PageRenderTime 188ms CodeModel.GetById 40ms RepoModel.GetById 1ms app.codeStats 1ms

/manual/phpfi2.php

https://github.com/Robervaldo/web-php
PHP | 7638 lines | 6754 code | 854 blank | 30 comment | 300 complexity | d678613bf0df6aa12b2164d01c894d48 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // $Id$
  3. $_SERVER['BASE_PAGE'] = 'manual/phpfi2.php';
  4. include_once $_SERVER['DOCUMENT_ROOT'] . '/include/prepend.inc';
  5. site_header('PHP/FI Version 2.0 Documentation');
  6. ?>
  7. <!--
  8. Documentation is like sex: when it is good, it is very, very good; and
  9. when it is bad, it is better than nothing.
  10. ++ Dick Brandon
  11. -->
  12. <h1 style="text-align: center;">PHP/FI Version 2.0</h1>
  13. <h1>Table of Contents</h1>
  14. <ol>
  15. <li><a href="#history">Brief History</a></li>
  16. <li><a href="#install">Installation Instructions</a></li>
  17. <li><a href="#starting">So, what can I do with PHP/FI?</a></li>
  18. <li><a href="#redirect">CGI Redirection</a></li>
  19. <li><a href="#security">Security Issues</a></li>
  20. <li><a href="#safemode">Safe Mode</a></li>
  21. <li><a href="#commandline">Running PHP/FI from the Command
  22. Line</a></li>
  23. <li><a href="#http_auth">HTTP Authentication</a></li>
  24. <li><a href="#requestvars">Apache Request Variables</a></li>
  25. <li><a href="#module">Apache Module Notes</a></li>
  26. <li><a href="#directives">Apache Module Configuration
  27. Directives</a></li>
  28. <li><a href="#fastcgi">FastCGI Support</a></li>
  29. <li><a href="#access">Access Control</a></li>
  30. <li><a href="#logging">Access Logging</a></li>
  31. <li><a href="#relative">Relative vs. Absolute URL's - or, Why
  32. do my Images Break?</a></li>
  33. <li>
  34. <a href="#getpost">How PHP/FI handles GET and POST method
  35. data</a>
  36. <ul>
  37. <li><a href="#selmul"><tt>SELECT MULTIPLE</tt> and
  38. PHP</a></li>
  39. <li><a href="#imagecoord"><tt>IMAGE SUBMIT</tt> and
  40. PHP</a></li>
  41. </ul>
  42. </li>
  43. <li><a href="#gd_support">GD (a graphics library for GIF
  44. creation) Support in PHP</a></li>
  45. <li><a href="#virtual_hosts">PHP/FI and Virtual Hosts</a></li>
  46. <li><a href="#upload">File Upload Support</a></li>
  47. <li><a href="#cookies">Cookie Support</a></li>
  48. <li><a href="#msql_support">mSQL Support</a></li>
  49. <li><a href="#pg95_support">Postgres95/PostgreSQL
  50. Support</a></li>
  51. <li><a href="#mysql_support">mysql Support</a></li>
  52. <li><a href="#solid_support">Solid Support</a></li>
  53. <li><a href="#sybase_support">Sybase Support</a></li>
  54. <li><a href="#oracle_support">Oracle Support</a></li>
  55. <li><a href="#illustra_support">Illustra Support</a></li>
  56. <li><a href="#adabas_support">Adabas Support</a></li>
  57. <li><a href="#regexp">Regular Expressions</a></li>
  58. <li><a href="#escapes">Escape Characters</a></li>
  59. <li><a href="#octal">Octal notation of Unix file
  60. permissions</a></li>
  61. <li>
  62. <a href="#script">PHP/FI Script Language</a>
  63. <ul>
  64. <li><a href="#syntax">Syntax</a></li>
  65. <li><a href="#vars">Variables</a></li>
  66. <li><a href="#assoc">Associative Arrays</a></li>
  67. <li><a href="#varvars">Variable Variables</a></li>
  68. <li><a href="#lang">Language Constructs</a></li>
  69. <li><a href="#user_funcs">User-Defined Functions</a></li>
  70. <li><a href="#scope">Scope of Variables</a></li>
  71. <li><a href="#math">Mathematical Expressions</a></li>
  72. <li><a href="#while">While Loops</a></li>
  73. <li><a href="#switch">Switch Construct</a></li>
  74. <li><a href="#secure">Secure Variables - Defeating GET
  75. method hacks</a></li>
  76. <li><a href="#overload">Overloaded Operators and dealing
  77. with variable types</a></li>
  78. <li><a href="#quiet">Suppressing Errors from function
  79. calls</a></li>
  80. <li><a href="#funcs">Internal Functions</a></li>
  81. </ul>
  82. </li>
  83. <li><a href="#addfunc">Adding your own functions to
  84. PHP/FI</a></li>
  85. <li><a href="#hacknotes">Notes for Code Hacks</a></li>
  86. </ol>
  87. <hr />
  88. <h2><a name="history" id="history">Brief History</a></h2>
  89. <p>PHP began life as a simple little cgi wrapper written in Perl.
  90. I wrote it in an afternoon during a period between contracts when
  91. I needed a quick tool to get an idea of who was reading my online
  92. resume. It was never intended to go beyond my own private use.
  93. The web server where I had my resume was extremely overloaded and
  94. had constant problems forking processes. I rewrote the Perl
  95. wrapper in C to get rid of the considerable overhead of having to
  96. fork Perl each time my resume was accessed.</p>
  97. <p>Eventually other people on the same web server came across my
  98. wrapper and asked if they could use it. Then, as inevitably
  99. happens, they started asking for more features. I added more
  100. features and finally put together a semi-complete distribution
  101. along with documentation, a mailing-list and a FAQ. The name of
  102. this first package was Personal Home Page Tools, which later
  103. became Personal Home Page Construction Kit.</p>
  104. <p>At the same time I started playing with databases and wrote a
  105. tool to easily embed SQL queries into web pages. It was basically
  106. another CGI wrapper that parsed SQL queries and made it easy to
  107. create forms and tables based on these queries. This tool was
  108. named FI (Form Interpreter).</p>
  109. <p>PHP/FI version 2.0 is a complete rewrite of these two packages
  110. combined into a single program. It has now evolved to the point
  111. where it is a simple programming language embedded inside HTML
  112. files. The original acronym, PHP, has stuck. It isn't really
  113. appropriate any longer. PHP/FI is used more for entire web sites
  114. today than for small Personal Home Page setups. By whatever name,
  115. it eliminates the need for numerous small Perl cgi programs by
  116. allowing you to place simple scripts directly in your HTML files.
  117. This speeds up the overall performance of your web pages since
  118. the overhead of forking Perl several times has been eliminated.
  119. It also makes it easier to manage large web sites by placing all
  120. components of a web page in a single html file. By including
  121. support for various databases, it also makes it trivial to
  122. develop database enabled web pages. Many people find the embedded
  123. nature much easier to deal with than trying to create separate
  124. HTML and CGI files.</p>
  125. <p>PHP Version 3.0 is yet another rewrite. If you are just
  126. starting out with PHP, I suggest that you start with Version 3.0
  127. instead of continuing with 2.0 at this point. PHP3 is quickly
  128. going to replace PHP/FI 2.0 and all development efforts are now
  129. focused on PHP3. Any remaining bugs in PHP/FI 2.0 are unlikely to
  130. be fixed unless they are straightforward. More information on
  131. PHP3 can be found at <a href=
  132. "http://www.lerdorf.on.ca/php3/">http://www.lerdorf.on.ca/php3</a>.</p>
  133. <p>Throughout this documentation any references to PHP, FI or
  134. PHP/FI all refer to the same thing. The difference between PHP
  135. and FI is only a conceptual one. Both are built from the same
  136. source distribution. When I build the package without any access
  137. logging or access restriction support, I call my binary FI. When
  138. I build with these options, I call it PHP.</p>
  139. <hr />
  140. <h2><a name="install" id="install">Installation
  141. Instructions</a></h2>
  142. <dl>
  143. <dt><big>Before You Begin</big></dt>
  144. <dd>
  145. <p>If you have absolutely no Unix experience, you may want to
  146. ask around for someone with a little bit of Unix knowledge to
  147. help you through this installation. Every attempt has been
  148. made to make it as simple as possible, but since the software
  149. is quite involved and relies on a number of different
  150. components, it is not realistic to assume it will go smoothly
  151. on all systems. You will probably need someone around who
  152. knows the particulars of the destination system well.</p>
  153. </dd>
  154. <dt><big>Things You Need To Know Before
  155. Installing</big></dt>
  156. <dd>
  157. <p>- Can you run both get and post method cgi programs on
  158. your server?<br />
  159. <em>This is not relevant if you installing the Apache module
  160. version.</em> If not, you can not use this package. On many
  161. public ISP's CGI programs are either disallowed or severely
  162. restricted. If this is the case on your system, talk to your
  163. system administrator and ask him/her to have a look at this
  164. package and see if they will install it for you.</p>
  165. </dd>
  166. <dd>
  167. <p>- If you have mSQL installed on your system, you need to
  168. know the base directory of this installation.</p>
  169. </dd>
  170. <dd>
  171. <p>- If you have Postgres95 or PostgreSQL installed on your
  172. system, you need to know the base directory of this
  173. installation.</p>
  174. </dd>
  175. <dd>
  176. <p>- If you are going to be storing log and access
  177. configuration files in an NFS-mounted directory and your
  178. system does not provide NFS file locking then you will need
  179. to define the NFS_HACK variable manually in the src/Makefile
  180. and you may want to use a slightly modified version of the
  181. gdbm library. See the <strong>nfs_hack.txt</strong> file in
  182. the doc directory for more information on this.</p>
  183. </dd>
  184. <dd>
  185. <p>- Note that if you are not interested in using PHP to
  186. track accesses to your pages, do not compile this option into
  187. the binary. You should also leave out the access restriction
  188. code. There is considerable overhead in including these
  189. options.</p>
  190. </dd>
  191. <dd>
  192. <p>- If you are installing the Apache module version, you
  193. will need to know the Apache src code directory location.</p>
  194. </dd>
  195. <dt><big>Installation Steps</big></dt>
  196. <dd>
  197. <p><em><strong>Step 1.</strong></em></p>
  198. <p>Run the install program: <tt>./install</tt></p>
  199. <p>You will be asked a number of questions. If you do not
  200. understand what is being asked, simply hit return. The
  201. default choice should be safe on most systems. This doesn't
  202. apply for the questions asking you to specify a directory for
  203. your configuration and log files however. Choose any
  204. directory to which the httpd (usually "nobody") has write
  205. privileges. You may create this directory manually somewhere
  206. and simply <strong><tt>chown nobody
  207. directory</tt></strong>.</p>
  208. <p><em><strong>Step 2.</strong></em></p>
  209. <p>Go into the src directory: <tt>cd src</tt></p>
  210. <p>Have a look at the php.h file. There are a number of
  211. compile-time options that can be set here.</p>
  212. <p><em><strong>Step 3.</strong></em></p>
  213. <p>type: <tt>make</tt></p>
  214. <p>This will create the actual executable program file named
  215. <em>php.cgi</em> by default, or if you are installing the
  216. Apache module, it will create a <em>libphp.a</em> file.</p>
  217. <p><em><strong>Step 4. (if you are not installing the Apache
  218. module version)</strong></em></p>
  219. <p>Copy the <strong>php.cgi</strong> binary to your system's
  220. cgi-bin directory. If you do not have access to do this and
  221. wish to install it in your own personal directory, you may do
  222. so, but you should set the setuid bit on the executable with:
  223. <tt>chmod u+s /path/php.cgi</tt></p>
  224. <p>If you do not make set the setuid bit on the binary then
  225. any files created by the binary will be owned by the user id
  226. under which the web server runs. If this is acceptable, then
  227. you can safely leave the setuid bit off.</p>
  228. <p><em><strong>Step 4. (if you are installing the Apache
  229. module version)</strong></em><br />
  230. Change to your Apache src directory where the
  231. <em>mod_php.c</em> and <em>mod_php.h</em> files should have
  232. been copied to. If they weren't which usually happens because
  233. of permission problems, copy these two files there manually.
  234. Edit your Apache Configuration file and add the EXTRA_LIBS
  235. line which was produced at the end of <strong>Step
  236. 3</strong>. And add:</p>
  237. <p><tt><strong>Module php_module mod_php.o</strong></tt></p>
  238. <p>to the very end of the file. Then type:
  239. <strong>./Configure</strong> and then <strong>make</strong>
  240. to rebuild your Apache httpd binary. Install this binary.</p>
  241. <p>Next you need to edit your Apache conf/srm.conf file and
  242. add a line like:</p>
  243. <p><tt><strong>AddType application/x-httpd-php
  244. .phtml</strong></tt></p>
  245. <p>This defines a new MIME, application/x-httpd-php, which
  246. will trigger the PHP module to parse any file ending with the
  247. <em>.phtml</em> extension. You can pick any extension you
  248. like for this.</p>
  249. <p>You may not want to enable everyone to run PHP parsed
  250. files. You can place the above AddType line within
  251. &lt;Location /path&gt;....&lt;/Location&gt; directives in the
  252. <em>access.conf</em> file to only allow PHP-parsed documents
  253. in certain directories on your server.</p>
  254. <p>Now you are ready to restart your httpd server. See the
  255. <a href="#module">Apache Module Notes</a> for more details on
  256. configuring the PHP Module.</p>
  257. </dd>
  258. <dt><big>Testing the software</big></dt>
  259. <dd>
  260. <p>Once installed you can test to see if your executable
  261. works by entering a URL similar to the following in your
  262. browser:</p>
  263. <p><tt>http://your.site.domain/cgi-bin/php.cgi</tt></p>
  264. <p>This should show you a page which contains the version
  265. number along with various other useful information.</p>
  266. <p>To test the Apache module version, create any file with a
  267. .phtml extension and put a tag like: &lt;?phpinfo()&gt; in
  268. the file and see if it gets parsed.</p>
  269. </dd>
  270. <dt><big>Using the software</big></dt>
  271. <dd>
  272. <p>To actually use the software on an existing HTML file, you
  273. can simply append the path to your file to the above URL.
  274. ie.</p>
  275. <p>
  276. <tt>http://your.site.domain/cgi-bin/php.cgi/path/file.html</tt></p>
  277. <p>You should have a look at the <a href="#redirect">CGI
  278. Redirection</a> section of this documentation. Running PHP/FI
  279. through a redirect means you can automatically have a URL
  280. like <em>http://your.site.domain/file.phtml</em> be parsed by
  281. PHP/FI.</p>
  282. <p>This does not apply to Apace module users.</p>
  283. </dd>
  284. </dl>
  285. <hr />
  286. <h2><a name="starting" id="starting">So, what can I do with
  287. PHP/FI?</a></h2>
  288. <p>The first thing you will notice if you run a page through
  289. PHP/FI is that it adds a footer with information about the number
  290. of times your page has been accessed (if you have compiled access
  291. logging into the binary). This is just a very small part of what
  292. PHP/FI can do for you. It serves another very important role as a
  293. form interpreter cgi, hence the FI part of the name. For example,
  294. if you create a form on one of your web pages, you need something
  295. to process the information on that form. Even if you just want to
  296. pass the information to another web page, you will have to have a
  297. cgi program do this for you. PHP/FI makes it extremely easy to
  298. take form data and do things with it.</p>
  299. <p><em><strong>A simple example</strong></em></p>
  300. <p>Suppose you have a form:</p>
  301. <p><tt>&lt;FORM ACTION="/cgi-bin/php.cgi/~userid/display.html"
  302. METHOD=POST&gt;<br />
  303. &lt;INPUT TYPE="text" name="name"&gt;<br />
  304. &lt;INPUT TYPE="text" name="age"&gt;<br />
  305. &lt;INPUT TYPE="submit"&gt;<br />
  306. &lt;/FORM&gt;</tt></p>
  307. <p>Your display.html file could then contain something like:</p>
  308. <p><tt>&lt;?echo "Hi $name, you are $age years
  309. old!&lt;p&gt;"&gt;</tt></p>
  310. <p>It's that simple! PHP/FI automatically creates a variable for
  311. each form input field in your form. You can then use these
  312. variables in the ACTION URL file.</p>
  313. <p>The next step once you have figured out how to use variables
  314. is to start playing with some logical flow tags in your pages.
  315. For example, if you wanted to display different messages based on
  316. something the user inputs, you would use if/else logic. In our
  317. above example, we can display different things based on the age
  318. the user entered by changing our display.html to:</p>
  319. <pre>
  320. &lt;?
  321. if($age&gt;50);
  322. echo "Hi $name, you are ancient!&lt;p&gt;";
  323. elseif($age&gt;30);
  324. echo "Hi $name, you are very old!&lt;p&gt;";
  325. else;
  326. echo "Hi $name.";
  327. endif;
  328. &gt;
  329. </pre>
  330. <p>PHP/FI provides a very powerful scripting language which will
  331. do much more than what the above simple example demonstrates. See
  332. the section on the <a href="#script">PHP/FI Script Language</a>
  333. for more information.</p>
  334. <p>You can also use PHP/FI to configure who is allowed to access
  335. your pages. This is done using a built-in configuration screen.
  336. With this you could for example specify that only people from
  337. certain domains would be allowed to see your pages, or you could
  338. create a rule which would password protect certain pages. See the
  339. <a href="#access">Access Control</a> section for more
  340. details.</p>
  341. <p>PHP/FI is also capable of receiving file uploads from any
  342. RFC-1867 compliant web browser. This feature lets people upload
  343. both text and binary files. With PHP/FI's access control and
  344. logical functions, you have full control over who is allowed to
  345. upload and what is to be done with the file once it has been
  346. uploaded. See the <a href="#upload">File Upload</a> section for
  347. more details.</p>
  348. <p>PHP/FI has support for a database package called mSQL. This
  349. allows you to put information into a database and access this
  350. information through simple embedded SQL queries right in your
  351. .HTML files. Adding a database back-end to a web page has never
  352. been easier. See the section on <a href="#msql_support">mSQL
  353. Support</a> for more information.</p>
  354. <p>PHP/FI has support for the Postgres95/PostgreSQL database
  355. package. It supports embedded SQL queries in your .HTML files.
  356. See the section on <a href="#pg95_support">Postgres95/PostgreSQL
  357. Support</a> for more information.</p>
  358. <p>PHP/FI also has support for the mysql database package. It
  359. supports embedded SQL queries in your .HTML files. See the
  360. section on <a href="#mysql_support">mysql Support</a> for more
  361. information.</p>
  362. <hr />
  363. <h2><a name="redirect" id="redirect">CGI Redirection</a></h2>
  364. <dl>
  365. <dt><strong>Apache 1.0.x Notes</strong></dt>
  366. <dd>
  367. <p>A good way to run PHP/FI is by using a cgi redirection
  368. module with the Apache server. Please note that you do not
  369. need to worry about redirection modules if you are using the
  370. Apache module version of PHP/FI. There are two of these
  371. redirection modules available. One is developed by Dave
  372. Andersen &lt;angio@aros.net&gt; and it is available at
  373. <a href=
  374. "ftp://ftp.aros.net/pub/util/apache/mod_cgi_redirect.c">ftp://ftp.aros.net/pub/util/apache/mod_cgi_redirect.c</a>
  375. and the other comes bundled with Apache and is called
  376. mod_actions.c. The modules are extremely similar. They differ
  377. slightly in their usage. Both have been tested and both work
  378. with PHP/FI.</p>
  379. <p>One large caveat at the time of this writing (Apr.20/96)
  380. is that the current official Apache release (1.0.5) has a
  381. severe limitation which prevents cgi redirected requests from
  382. having any post-method data associated with them. I have
  383. tracked this down and fixed it in my version of Apache, and
  384. there is an official patch available in the <a href=
  385. "http://php.iquest.net/files/">File Archives</a> on the
  386. <a href="http://php.iquest.net/">PHP Home Page</a>.</p>
  387. <p>A second rather large caveat with Apache 1.0.x is that it
  388. does not align double types correctly on most architectures.
  389. You may find yourself getting strange bus errors from your
  390. httpd when using mod_php, either upgrade to Apache 1.1 or
  391. edit the <i>alloc.c</i> Apache source file. In this file you
  392. will find the following piece of code:</p>
  393. <pre>
  394. union align
  395. {
  396. /* Types which are likely to have the longest RELEVANT alignment
  397. * restrictions... we don't do much with doubles.
  398. */
  399. char *cp;
  400. void (*f)();
  401. long l;
  402. FILE *fp;
  403. };
  404. </pre>
  405. <p>You will need to add a double to this line and recompile
  406. your Apache server. The correct block of code is:</p>
  407. <pre>
  408. union align
  409. {
  410. /* Types which are likely to have the longest RELEVANT alignment
  411. * restrictions... we don't do much with doubles.
  412. */
  413. char *cp;
  414. void (*f)();
  415. long l;
  416. FILE *fp;
  417. double d;
  418. };
  419. </pre>
  420. <p>These problems have all been fixed in later versions of
  421. Apache.</p>
  422. <p>Check the Apache documentation on how to add a module.
  423. Generally you add the module name to a file called
  424. <em>Configuration</em>. The line to be added if you want to
  425. use the mod_actions module is:</p>
  426. <p><tt>Module action_module mod_actions.o</tt></p>
  427. <p>If you are using the mod_cgi_redirect.c module add this
  428. line:</p>
  429. <p><tt>Module cgi_redirect_module mod_cgi_redirect.o</tt></p>
  430. <p>Then compile your httpd and install it. To configure the
  431. cgi redirection you need to either create a new mime type in
  432. your <em>mime.types</em> file or you can use the
  433. <strong>AddType</strong> command in your <em>srm.conf</em>
  434. file to add the mime type. The mime type to be added should
  435. be something like this:</p>
  436. <p><tt>application/x-httpd-php phtml</tt></p>
  437. <p>If you are using the mod_actions.c module you need to add
  438. the following line to your <em>srm.conf</em> file:</p>
  439. <p><tt>Action application/x-httpd-php
  440. /cgi-bin/php.cgi</tt></p>
  441. <p>If you are using mod_cgi_redirect.c you should add this
  442. line to <em>srm.conf</em>:</p>
  443. <p><tt>CgiRedirect application/x-httpd-php
  444. /cgi-bin/php.cgi</tt></p>
  445. <p>Don't try to use both mod_actions.c and mod_cgi_redirect.c
  446. at the same time.</p>
  447. <p>Once you have one of these cgi redirection modules
  448. installed and configured correctly, you will be able to
  449. specify that you want a file parsed by php/fi simply by
  450. making the file's extension <strong>.phtml</strong>.
  451. Furthermore, if you add <strong>index.phtml</strong> to your
  452. <strong>DirectoryIndex</strong> configuration line in your
  453. <em>srm.conf</em> file then the top-level page in a directory
  454. will be automatically parsed by php if your index file is
  455. called index.phtml.</p>
  456. </dd>
  457. <dt><strong>Netscape HTTPD</strong></dt>
  458. <dd>
  459. <p>You can automatically redirect requests for files with a
  460. given extension to be handled by PHP/FI by using the Netscape
  461. Server CGI Redirection module. This module is available in
  462. the <a href="http://php.iquest.net/files/">File Archives</a>
  463. on the <a href="http://php.iquest.net/">PHP/FI Home Page</a>.
  464. The README in the package explicitly explains how to
  465. configure it for use with PHP/FI.</p>
  466. </dd>
  467. <dt><strong>NCSA HTTPD</strong></dt>
  468. <dd>
  469. <p>NCSA does not currently support modules, so in order to do
  470. cgi redirection with this server you need to modify your
  471. server source code. A patch to do this with NCSA 1.5 is
  472. available in the <a href=
  473. "http://php.iquest.net/files/">PHP/FI file archives</a>.</p>
  474. </dd>
  475. </dl>
  476. <hr />
  477. <h2><a name="security" id="security">Security Issues</a></h2>
  478. <p>The CGI version of PHP/FI does <strong>not</strong> read any
  479. <em>.htaccess</em> files which may be present in a directory.
  480. This means that if you have files that are protected using the
  481. standard .htaccess server-based access control feature, people
  482. could potentially circumvent this security by loading the page
  483. through PHP/FI. Note that this is not an issue for the Apache
  484. module version of PHP/FI.</p>
  485. <p>A second problem with the CGI version is that if it is placed
  486. in the system's cgi-bin directory it can be used to view any file
  487. on your system as long as the user id it runs as has access to
  488. it.</p>
  489. <p>There are a couple of different solutions to this problem. The
  490. easiest is probably to use the <strong>PATTERN_RESTRICT</strong>
  491. feature found in <em>php.h</em>. This lets you define an
  492. extension (or a pattern of extensions) which are allowed to be
  493. parsed by PHP/FI. If a file does not have this extension and
  494. someone tries to load it with PHP/FI, an <em>access denied</em>
  495. message will appear.</p>
  496. <p>Another solution is to use the PHP/FI access control mechanism
  497. to mimic the access control setup you have in your .htaccess
  498. file. Keeping this information in two places can be tedious
  499. though, and the two systems don't share all of the same
  500. features.</p>
  501. <p>The problem can also be solved using file permissions. PHP/FI
  502. can be set up to run setuid as any user you wish. Then files that
  503. are to be read by PHP/FI can be given appropriate permissions and
  504. files not to be read by PHP/FI should be owned by another user id
  505. and have their permissions changed accordingly.</p>
  506. <p>For additional security options related to sites which provide
  507. shared access to PHP, see the <a href="#safemode">Safe Mode</a>
  508. section.</p>
  509. <hr />
  510. <h2><a name="safemode" id="safemode">Safe Mode</a></h2>
  511. <p>PHP's Safe Mode tries to solve the common problem faced by
  512. many ISP's regarding letting all their users run CGI programs.
  513. The common mechanism for making shared CGI access more secure is
  514. to use a cgi wrapper like the su_exec utility that comes with
  515. Apache. This will not work for PHP when it is running as a module
  516. because it is not a separate process that can be setuid'ed.</p>
  517. <p>It is based on a file permission scheme. Simply put, if a file
  518. is either owned by the same user id as the script that is trying
  519. to access it, or if the file is in a directory that is owned by
  520. the same user as the script that is trying to access it, then the
  521. access is allowed. One caveat here is that you must make sure
  522. that your OS does not allow non-root user to chown away the
  523. ownership on one of their files. Many older SysV systems allow
  524. this. The most common one is Irix. It is possible to change this
  525. behaviour at the OS level on Irix.</p>
  526. <p>Safe Mode applies to each function which could possibly be a
  527. security risk. Below is the current list of checks applied to
  528. each relevant function. In the following list, PHP UID refers to
  529. the user id of the owner of the current file being parsed by PHP,
  530. and HTTP UID refers to the user id the httpd process is running
  531. as (usually nobody).</p>
  532. <dl>
  533. <dt>Include, ReadFile, Fopen, File, Link, Unlink, Symlink,
  534. Rename, RmDir, ChMod, ChOwn, ChGrp</dt>
  535. <dd>Owner of file to be included must either be the PHP UID or
  536. the directory in which the file resides must be owned by the
  537. PHP UID.</dd>
  538. <dt>Exec, System, PassThru and Popen</dt>
  539. <dd>Executables to be forked and executed must reside in the
  540. directory defined by the PHP_SAFE_MODE_EXEC_DIR #define in
  541. php.h when PHP is compiled.</dd>
  542. <dt>Mysql_Connect</dt>
  543. <dd>This function takes an optional username to use to connect
  544. to an MySQL database. When in safe mode, this username must
  545. either be the username of the owner of the current file being
  546. parsed, or the name of the httpd user (usually nobody).</dd>
  547. <dt>HTTP Authentication</dt>
  548. <dd>The numerical user id of the owner of the script containing
  549. the HTTP Authentication code will be prepended to the
  550. authentication realm. This is to prevent someone from writing a
  551. password grabbing script which spoofs another authenticated
  552. page on the same server.</dd>
  553. </dl>
  554. <hr />
  555. <h2><a name="commandline" id="commandline">Running PHP/FI from
  556. the command line</a></h2>
  557. <p>If you build the CGI version of PHP/FI, you can use it from
  558. the command line simply typing: <tt>php.cgi filename</tt> where
  559. filename is the file you want to parse. You can also create
  560. standalone PHP/FI scripts by making the first line of your script
  561. look something like:</p>
  562. <pre>
  563. #!/usr/local/bin/php.cgi -q
  564. </pre>The "-q" suppresses the printing of the HTTP headers. You can
  565. leave off this option if you like.
  566. <hr />
  567. <h2><a name="http_auth" id="http_auth">HTTP
  568. Authentication</a></h2>
  569. <p>The HTTP Authentication hooks in PHP/FI are only available
  570. when it is running as an Apache module. In an Apache module
  571. PHP/FI script, it is possible to use the Header() command to send
  572. an "Authentication Required" message to the client browser
  573. causing it to pop up a Username/Password input window. Once the
  574. user has filled in a username and a password, the URL containing
  575. the PHP/FI script will be called again with the variables,
  576. $PHP_AUTH_USER, $PHP_AUTH_PW and $PHP_AUTH_TYPE set to the user
  577. name, password and authentication type respectively. Only "Basic"
  578. authentication is supported at this point.</p>
  579. <p>An example script fragment which would force client
  580. authentication on a page would be the following:</p>
  581. <pre>
  582. &lt;?
  583. if(!$PHP_AUTH_USER) {
  584. Header("WWW-authenticate: basic realm=\"My Realm\"");
  585. Header("HTTP/1.0 401 Unauthorized");
  586. echo "Text to send if user hits Cancel button\n"
  587. exit;
  588. } else {
  589. echo "Hello $PHP_AUTH_USER.&lt;P&gt;";
  590. echo "You entered $PHP_AUTH_PW as your password.&lt;P&gt;";
  591. }
  592. &gt;
  593. </pre>
  594. <p>Instead of simply printing out the $PHP_AUTH_USER and
  595. $PHP_AUTH_PW, you would probably want to check the username and
  596. password for validity. Perhaps by sending a query to a database,
  597. or by looking up the user in a dbm file.</p>
  598. <p>Watch out for buggy Internet Explorer browsers out there. They
  599. seem very picky about the order of the headers. Sending the
  600. <b>WWW-authenticate</b> header before the <b>HTTP/1.0 401</b>
  601. header seems to do the trick for now.</p>
  602. <p>In order to prevent someone from writing a script which
  603. reveals the password for a page that was authenticated through a
  604. traditional external mechanism, the PHP_AUTH variables will not
  605. be set if external authentication is enabled for that particular
  606. page.</p>
  607. <p>Note however that the above does not prevent someone who
  608. controls a non-authenticated URL from stealing passwords from
  609. authenticated URL's on the same server. The PHP_AUTH_VARS define
  610. in <em>php.h</em> can be undefined to make sure that these
  611. variables will never be set and thus disable anybody from using
  612. mod_php to try to steal passwords.</p>
  613. <hr />
  614. <h2><a name="requestvars" id="requestvars">Apache Request
  615. Variables</a></h2>
  616. <p>When running PHP as an Apache module, you may access the
  617. request header variables sent by the remote browser by prepending
  618. <b>$req_</b> to the beginning of the header value you would like
  619. to use. If the request name contains a <b>-</b> character such as
  620. User-Agent, then you need to map the - to _ (an underscore). ie.
  621. reference it as $req_User_Agent. The <a href=
  622. "#phpinfo">phpinfo()</a> function can be used to display all the
  623. request headers.</p>
  624. <p>eg.</p>
  625. <pre>
  626. &lt;
  627. echo "$req_connection&lt;br&gt;";
  628. echo "$req_host&lt;br&gt;";
  629. &gt;
  630. </pre>The above simple script might output:
  631. <pre>
  632. Keep-Alive
  633. www.host.com
  634. </pre>
  635. <hr />
  636. <h2><a name="module" id="module">Apache Module Notes</a></h2>
  637. <p>Running PHP/FI as an Apache module is the most efficient way
  638. of using the package. Running it as a module means that the
  639. PHP/FI functionality is combined with the Apache server's
  640. functionality in a single program. There are a number of
  641. advantages to running it as a module:</p>
  642. <dl>
  643. <dt><strong>Performance</strong></dt>
  644. <dd>
  645. <p>Performance-wise it is a lot faster than traditional CGI
  646. programs. In fact, when running PHP/FI as a module, there is
  647. no CGI involved. The script code in the HTML files is
  648. executed directly by the Apache web server process.</p>
  649. </dd>
  650. <dt><strong>Security</strong></dt>
  651. <dd>
  652. <p>When running as a module, the normal httpd-based access
  653. restriction rules defined either in the Apache conf files or
  654. in private .htaccess files are first applied before the
  655. module is allowed to parse the file. Alternatively, you can
  656. also create PHP/FI scripts that control the normal
  657. httpd-based authentication. See <a href="#http_auth">HTTP
  658. Authentication</a>.</p>
  659. </dd>
  660. <dt><strong>Configurability</strong></dt>
  661. <dd>
  662. <p>Since the parser is always active inside the httpd
  663. process, it can be configured on startup using the same
  664. configuration files used to configure the httpd process. The
  665. module can even be configured on a per-directory basis by
  666. placing the <a href="#directives">PHP configuration
  667. directives</a> in the <em>.htaccess</em> files.</p>
  668. </dd>
  669. <dt><strong>Basis for custom server-based
  670. function</strong></dt>
  671. <dd>
  672. <p>For C programmers interested in accessing their functions
  673. from within Apache, the PHP/FI framework provides a very
  674. simple interface to Apache and to PHP itself. It is much
  675. easier to add a function to PHP and call that from a parsed
  676. page than it is to write an entire Apache module from
  677. scratch. See the <a href="#addfunc">Adding your own internal
  678. functions to PHP/FI</a> sections at the end of this document
  679. for further details.</p>
  680. </dd>
  681. </dl>
  682. <h2><a name="directives" id="directives">Apache Module
  683. Configuration Directives</a></h2>
  684. <p>The following directives can be placed either in the
  685. <em>srm.conf</em> file, or within
  686. &lt;Directory&gt;...&lt;/Directory&gt; tags in
  687. <em>access.conf</em> or in &lt;Location
  688. /path&gt;...&lt;/Location&gt; tags in <em>access.conf</em> or in
  689. individual <em>.htaccess</em> files. In order for the directives
  690. to work in .htaccess files, the Options override must be set on
  691. the AllowOverride Apache directive, with the exception of the
  692. phpEngine directive which is only available in the *.conf
  693. files.</p>
  694. <dl>
  695. <dt><strong>phpShowInfo <em>on</em>|<em>off</em></strong></dt>
  696. <dd>Turn the PHP info footers on or off. Default is on.</dd>
  697. <dt><strong>phpLogging <em>on</em>|<em>off</em></strong></dt>
  698. <dd>Turn logging on or off. Default is on.</dd>
  699. <dt><strong>phpDebug <em>on</em>|<em>off</em></strong></dt>
  700. <dd>Turn automatic ?info debug screen on or off. Default is
  701. off.</dd>
  702. <dt><strong>phpUploadTmpDir <em>directory</em></strong></dt>
  703. <dd>Set the directory where form-uploaded files will be
  704. placed.</dd>
  705. <dt><strong>phpDbmLogDir <em>directory</em></strong></dt>
  706. <dd>Set the directory where dbm-based logging files will be
  707. written.</dd>
  708. <dt><strong>phpSQLLogDB <em>database</em></strong></dt>
  709. <dd>Set name of SQL database to use for logging. Default is
  710. "phpfi"</dd>
  711. <dt><strong>phpSQLLogHost <em>hostname</em></strong></dt>
  712. <dd>Set hostname where SQL database to use for logging is
  713. found. Default is localhost.</dd>
  714. <dt><strong>phpAccessDir <em>directory</em></strong></dt>
  715. <dd>Set the directory where PHP-internal access control files
  716. are stored.</dd>
  717. <dt><strong>phpMaxDataSpace <em>KiloBytes</em></strong></dt>
  718. <dd>Max size a sub-pool can grow to within the PHP module.
  719. Setting this value to a low number will minimize the impact
  720. that mod_php will have on your system, but it may also limit
  721. people from writing complex scripts. The default is 8K.</dd>
  722. <dt><strong>phpIncludePath <em>colon-separated
  723. path</em></strong></dt>
  724. <dd>A colon-separated list of directories where php will look
  725. for files in when running <a href="#include">include()</a>. The
  726. default is to look only in the current directory.</dd>
  727. <dt><strong>phpAutoPrependFile <em>file name</em></strong></dt>
  728. <dd>Before the actual PHP/FI file is parsed, you may give a
  729. file name here that is parsed before the "main file", using
  730. PHP's Include() function (which means phpIncludePath applies
  731. for the file name). Keep in mind that you can make it difficult
  732. for yourself to use the Header() function in the main file if
  733. you write HTML from an auto-prepended file.</dd>
  734. <dt><strong>phpAutoAppendFile <em>file name</em></strong></dt>
  735. <dd>The name of a file parsed (using PHP's Include()
  736. function)after the actual PHP/FI file has been parsed, similar
  737. to phpAutoPrependFile.</dd>
  738. <dt><strong>phpAdaDefDB <em>database</em></strong></dt>
  739. <dd>Default Adabas database to use. No default value</dd>
  740. <dt><strong>phpAdaUser <em>username</em></strong></dt>
  741. <dd>Default Adabas database user. No default value</dd>
  742. <dt><strong>phpAdaPW <em>password</em></strong></dt>
  743. <dd>Default Adabas database password. No default value</dd>
  744. <dt><strong>phpEngine <em>on</em>|<em>off</em></strong></dt>
  745. <dd>Turn the PHP parsing engine on or off. The default is
  746. <em>on</em> and this directive is only useful for sites that
  747. wish to allow directives from the AllowOverride Options list of
  748. directives to function in .htaccess files while at the same
  749. time restricting mod_php access. The common way to handle
  750. per-virtual host php installs is to enable the PHP mime type
  751. with an AddType directive on a per virtual host basis and then
  752. put "phpEngine off" in the non-PHP virtual host blocks. If a
  753. non PHP customer tries to circumvent things by placing the PHP
  754. mime type in their .htaccess, the phpEngine off setting
  755. restricts the PHP parser from functioning.</dd>
  756. <dt><strong>phpLastModified
  757. <em>on</em>|<em>off</em></strong></dt>
  758. <dd>Since php pages are dynamic, they are processed and sent to
  759. the browser each time you access them. But sometimes, when you
  760. use php for basic includes, the parsed page does not change as
  761. long as the source doesn't. It that case, you may want to avoid
  762. page regeneration/reloading. If phpLastModified is turned on
  763. Apache will send the Last-Modified tag to the browser, so that
  764. the page will only be reloaded when it changes. (not that if
  765. you are using page logging, multiple accesses will not be
  766. logged!)</dd>
  767. </dl>
  768. <p>All of these directives are optional. If a directive is not
  769. specified anywhere, the compile-time default will be used.</p>
  770. <hr />
  771. <h2><a name="fastcgi" id="fastcgi">FastCGI Support</a></h2>
  772. <p>PHP/FI can be compiled with FastCGI support. You will need
  773. fetch and compile <a href="http://www.fastcgi.com">FCGI
  774. Development Kit</a> for your platform before compiling PHP/FI.
  775. You will also need to get <a href="#redirect">CGI Redirection</a>
  776. working. Then follow the instructions in the FastCGI
  777. documentation for configuring FastCGI for your platform. If you
  778. are using the mod_fastcgi module with the Apache server, here are
  779. the step-by-step instructions:</p>
  780. <ul>
  781. <li>Edit your Apache Configuration file and add the mod_fastcgi
  782. module, then recompile Apache.</li>
  783. <li>Edit your <em>srm.conf</em> file and add lines similar
  784. to:<br />
  785. <tt>AddType application/x-httpd-fcgi .fcgi<br />
  786. AppClass /usr/local/etc/httpd/fcgi-bin/php.fcgi -processes
  787. 4<br />
  788. AddType application/x-httpd-fphp .fhtml<br />
  789. Action application/x-httpd-fphp
  790. /fcgi-bin/php.fcgi<br /></tt></li>
  791. <li>Copy your <em>php.cgi</em> binary to
  792. <em>/usr/local/etc/httpd/fcgi-bin/php.fcgi</em></li>
  793. </ul>
  794. <p>Now, any pages with the .fhtml extension will be handed off to
  795. the FastCGI php.fcgi process which is already running. The
  796. php.fcgi binary will still work as a normal CGI binary, so you
  797. could just create a symbolic link from php.cgi to php.fcgi.</p>
  798. <p>If you are not using Apache, the above steps will be similar,
  799. but not identical. CGI Redirection mechanisms are available for
  800. NCSA and Netscape servers at the <a href=
  801. "http://php.iquest.net/files/">PHP/FI File Archive</a>.</p>
  802. <hr />
  803. <h2><a name="access" id="access">Access Control</a></h2>
  804. <p>Note that the built-in PHP/FI based access control is likely
  805. to be discontinued in future versions. You should seriously
  806. consider using the security mechanism that comes with your web
  807. server instead.</p>
  808. <p>If you chose to include access control when you compiled the
  809. package, you may append <em>?config</em> to any URL to edit the
  810. access control file. ie.</p>
  811. <p>
  812. <tt>http://your.machine.domain/cgi-bin/php.cgi/path/file.html?config</tt></p>
  813. <p>Your configuration password will initially be set to your user
  814. id. If your user id does not work as your password, it probably
  815. means that PHP could not read the /etc/passwd file to locate your
  816. user id. If this is the case, the initial password will be set to
  817. "<strong>php</strong>". It is a good idea to change this
  818. password. Note that multiple users may maintain their own
  819. personal configuration files through a single PHP/FI binary.</p>
  820. <p>Access Control can be quite confusing initially. The ?config
  821. screen is divided up into a number of sections. The top section
  822. is for changing the password used to make sure that only people
  823. who know this password can change access control characteristics.
  824. In a system-wide installation, each user has his or her own
  825. configuration screen with his or her own password.</p>
  826. <p>The second section of the ?config screen consists of a number
  827. of tables. Each table defines a rule-set. The first rule-set is
  828. always the default rule-set. This default rule-set is used if a
  829. page does not have a rule-set defined specifically for it. After
  830. the default rule-set, any number of specific rule-set tables will
  831. follow.</p>
  832. <p>To add a rule-set for a specific file, enter the URL of the
  833. file in your browser and add <em><strong>?config</strong></em> to
  834. the end of the URL. On the ?config screen that comes up you will
  835. see that a rule-set has been added for this page, if it wasn't
  836. already there. When a new rule-set is added, it is initially set
  837. to be the same as the default rule-set. The following picture
  838. shows two simple rule-sets. First a default rule-set which just
  839. indicates that hits from all domains should be logged, and
  840. second, for the file /~rasmus/test.html and only that file, any
  841. users coming from a "<em>.edu</em>" domain will not be granted
  842. access.</p>
  843. <p><img src="gifs/config.gif" alt=
  844. "[Image of ?config screen]" /></p>
  845. <p>To edit a rule-set modify the fields until the desired
  846. configuration is reached within a rule-set and then hit the
  847. "<em>Submit Changes</em>" button. If more rules are needed, hit
  848. the "<em>Add Rule</em>" button and then edit the added rule.</p>
  849. <p>To delete a rule, select the checkbox to the right of the rule
  850. and hit the "<em>Submit Changes</em>" button. The screen will
  851. redraw and the rule should disappear.</p>
  852. <p>Note that you need to enter a regular expression in the
  853. pattern field. See the section on regular expressions in this
  854. documentation for more details.</p>
  855. <hr />
  856. <h2><a name="logging" id="logging">Access Logging</a></h2>
  857. <p>Access Logging is another optional feature which can be
  858. enabled at compile-time by answering <em>Yes</em> to the question
  859. in the install script. You may either store your access log data
  860. in dbm files, in an mSQL database, or in an mysql database. The
  861. latter two are more powerful, but is also a bit more difficult to
  862. set up.</p>
  863. <p>To use dbm files for storing your access logs, you will need
  864. to specify a directory in which log files can be written. PHP
  865. will try to create this directory if it doesn't exist, but to
  866. make sure it has the proper permissions, you may want to create
  867. this directory yourself before running PHP for the first time.
  868. The permissions on the directory should be such that the user id
  869. under which the PHP cgi program will run can write to the
  870. directory.</p>
  871. <p>To use an mSQL or mysql database for storing your access log
  872. data, you need to first make sure you have mSQL or mysql
  873. installed and running on your system. Then you need to create a
  874. database. The default name is "phpfi" although this can be
  875. changed in <em>src/php.h</em>. To create this database for mSQL,
  876. type:</p>
  877. <pre>
  878. msqladmin create phpfi
  879. </pre>
  880. <p>or for mysql type:</p>
  881. <pre>
  882. mysqladmin create phpfi
  883. </pre>
  884. <p>Then for mSQL, edit your <em>msql.acl</em> file and make sure
  885. the permissions on the database are correct. Something like the
  886. following should suffice:</p>
  887. <pre>
  888. database=phpfi
  889. read=*
  890. write=nobody,&lt;your user id&gt;
  891. access=local
  892. </pre>
  893. <p>For mysql, you need to make sure the httpd user (usually
  894. "nobody") has access to the database. Unlike mSQL, mysql stores
  895. access control data in a database. Assuming default permissions,
  896. you should be able to simply execute the following command:</p>
  897. <pre>
  898. echo "INSERT INTO user VALUES ('localhost','nobody','','Y','Y','Y','Y','Y','Y','Y','Y','Y');" | mysql mysql
  899. </pre>
  900. <p>Don't forget to load this new configuration with:</p>
  901. <pre>
  902. mysqladmin reload
  903. </pre>
  904. <p>For each user id for whom you want to store log data, you need
  905. to create two tables. The <em>msqllog</em> shell script in the
  906. scripts directory will do this for you. Simply type:</p>
  907. <pre>
  908. msqllog &lt;user id&gt;
  909. </pre>
  910. <p>or for mysql, type:</p>
  911. <pre>
  912. mysqllog &lt;user id&gt;
  913. </pre>
  914. <p>and the script will create the appropriate tables. You may
  915. need to edit the script to make it reflect where things are
  916. stored on your system.</p>
  917. <p>You may want to have a look at this script. It defines the
  918. field sizes of your log tables. If, for example, you know that
  919. your file paths exceed 64 characters, you need to bump up the
  920. filename size in both the <em>logN</em> and the <em>lastN</em>
  921. tables in this <em>msqllog</em> or <em>mysqllog</em> file.</p>
  922. <p>Access logging stores information about each "hit" on a page.
  923. This information can then be summarized by examining these log
  924. files. An example log file summarizing script is included in the
  925. package. It is the <tt>log.html</tt> file in the
  926. <tt>examples</tt> directory. This is the dbm log file analyzer.
  927. The mSQL log file analyzer is called <tt>mlog.html</tt>. And the
  928. mysql log file analyzer is called <tt>mylog.html</tt>. To run it,
  929. copy it and the other mlog.* files to a directory accessible from
  930. your web server and type:</p>
  931. <pre>
  932. http://your.machine.domain/cgi-bin/php.cgi/path/mlog.html
  933. </pre>
  934. <p>Or, if you are using the Apache module version, you can give
  935. the script a ".phtml" extension and call it with:</p>
  936. <pre>
  937. http://your.machine.domain/path/mlog.phtml
  938. </pre>
  939. <p>By default, if you have compiled PHP with access logging
  940. enabled, then your pages will appear with a footer containing
  941. some access information. You may not want to see this footer, but
  942. still log hits. You can turn off this footer with a "phpShowInfo
  943. off" line in your Apache httpd.conf or .htaccess files if you are
  944. running Apache. If you are not running Apache, you may turn these
  945. log footers off either by creating a rule in the <a href=
  946. "#access">?config</a> section for the page, or by adding a tag
  947. like this to your page:</p>
  948. <p><tt>&lt;?setshowinfo(0)&gt;</tt></p>
  949. <hr />
  950. <h2><a name="relative" id="relative">Relative vs. Absolute URL's
  951. - or, Why do my Images Break?</a></h2>
  952. <p>A problem common to all CGI wrappers is that the HTTPD program
  953. changes the current directory to the directory where whatever it
  954. is loading is stored. In the case of a CGI program, the current
  955. directory is set to the directory where the CGI program resides.
  956. This is normally not a problem, except when it comes to relative
  957. URL's.</p>
  958. <p>A relative URL is a URL which relies upon the current
  959. directory being the same as the directory where the current HTML
  960. file is located. So, for example, if I had the URL:</p>
  961. <pre>
  962. http://my.machine/~rasmus/file.html
  963. </pre>
  964. <p>the actual HTML file might be:</p>
  965. <pre>
  966. ~rasmus/public_html/file.html
  967. </pre>
  968. <p>If within the <tt>file.html</tt> file I had the tag:</p>
  969. <pre>
  970. &lt;IMG SRC="pic.gif"&gt;
  971. </pre>
  972. <p>when loaded normally this file gif file is expected to be in
  973. <tt>~rasmus/public_html/pic.gif</tt>. However, when loaded
  974. through a CGI wrapper with a URL like:</p>
  975. <pre>
  976. http://my.machine/cgi-bin/php.cgi/~rasmus/file.html
  977. </pre>
  978. <p>then HTTPD sets the current directory to <tt>/cgi-bin</tt> (or
  979. wherever the ScriptAlias might point) and subsequently when the
  980. page is loaded the <tt>pic.gif</tt> file is expected to be in:
  981. <tt>/cgi-bin/pic.gif</tt> which is usually not the desired
  982. effect.</p>
  983. <p>The quick way around this problem is to use absolute URL's. In
  984. the above example if the image tag had been:</p>
  985. <pre>
  986. &lt;IMG SRC="/~rasmus/pic.gif"&gt;
  987. </pre>
  988. <p>then there would have been no problem. Using absolute URL's is
  989. not always desirable as it makes pages less portable. An obvious
  990. question you may have at this point is, "Why doesn't PHP just
  991. change the current directory to the right place?". The answer is
  992. that PHP actually does change the current directory to the
  993. location of the HTML file it is displaying. Any file paths used
  994. inside PHP Script tags, can be relative. The problem is that tags
  995. outside of PHP's control such as &lt;img &gt; and &lt;a href &gt;
  996. will not be passed through PHP. When they are parsed, PHP is no
  997. longer active and the current working directory has been set back
  998. to the directory specified by the HTTP Daemon.</p>
  999. <p><strong>The Solution</strong> is a compromise. PHP provides a
  1000. variable called <strong>PATH_DIR</strong>. It contains the
  1001. directory portion of the current HTML file at all times. If this
  1002. PATH_DIR variable is used in the &lt;img &gt; and &lt;a href &gt;
  1003. tags then th

Large files files are truncated, but you can click here to view the full file