<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AskApache &#187; Search Results  &#187;  socket</title>
	<atom:link href="http://www.askapache.com/search/socket/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.askapache.com</link>
	<description>Advanced Web Development</description>
	<lastBuildDate>Thu, 26 Apr 2012 11:29:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Chmod, Umask, Stat, Fileperms, and File Permissions</title>
		<link>http://www.askapache.com/security/chmod-stat.html</link>
		<comments>http://www.askapache.com/security/chmod-stat.html#comments</comments>
		<pubDate>Fri, 17 Feb 2012 11:16:56 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[chmod]]></category>
		<category><![CDATA[File Permissions]]></category>
		<category><![CDATA[umask]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=1800</guid>
		<description><![CDATA[<p><a class="IFL" id="id8" href="http://www.askapache.com/security/chmod-umask-fileperms-stat-tricks.html"></a>Unix file permissions are one of the more difficult subjects to grasp.. Well, ok maybe "grasp" isn't the word.. Master is the right word.. Unix file permissions is a hard topic to fully master, mainly I think because there aren't many instances when a computer user encounters them seriously, and bitwise is oldschool.  This contains a listing of all possible permission masks and bits from a linux, php, and web hosting view.... cuz you guys <em>AskApache Regs</em> Rock! <br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/security/chmod-stat.html"></a><a href="http://www.askapache.com/security/chmod-stat.html"><cite>AskApache.com</cite></a></p><p><a class="IFL" id="id8" href="http://www.askapache.com/security/chmod-stat.html"></a>Unix file permissions are one of the more difficult subjects to grasp.. Well, ok maybe "grasp" isn't the word.. Master is the right word.. Unix file permissions is a hard topic to fully master, mainly I think because there aren't many instances when a computer user encounters them.   Windows has been trying to figure it out for decades with little progress, so don't feel bad if you don't know much about it.  <strong>Unless you're with the program</strong> and running Mac or any other <a href="http://www.archlinux.org/">BSD/Unix</a> based OS you've never had the ability to secure your system in this most basic and fundamental way.  Usually the first time someone encounters file permissions it's because their website was cracked.. <br class="C" /></p>

<h3>.htaccess</h3>
<p><kbd>$ chmod 604 .htaccess</kbd></p>
<pre>
604 -rw----r--  /home/askapache/cgi-bin/.htaccess
</pre>


<h3>php.cgi</h3>
<p><kbd>$ chmod 711 php.cgi</kbd></p>
<pre>
$ 711 -rwx--x--x  /home/askapache/cgi-bin/php.cgi
</pre>


<h3>.php.ini</h3>
<p><kbd>$ chmod 600 php.ini</kbd></p>
<pre>
$ 600 -rw-------  /home/askapache/cgi-bin/php.ini
</pre>

<p>I'm in the process of developing an updated version of the .htaccess security plugin, and one thing I have been working on is file permissions.  Some people had problems trying to create files on their server and I realized it was bad programming on my part..  so I began researching permissions in detail. I went deep into the source code of Apache (<em>which is why this site is called AskApache, BTW</em>), PHP, Python, Ocaml, Perl, Ruby, and POSIX operating systems and got a pretty good handle on it now..</p>

<h2>Tips before we dig in</h2>
<p>Here's a few things I've learned that I didn't know before (using php).</p>

<h3>Deleting Files and Directories</h3>
<p>Deleting a file may require chmodding the file to 666 or even 777 before you are able to delete it.  You also might have to chmod the parent directory of the file as well.  Also, you may have to chdir to the directory the file is in.  And lastly you may have to change the owner or group of the file.  Further than that you can try renaming the file first then deleting it..</p>
<p>Deleting a directory means you need to remove every file in it first.  It needs to be empty.  And if your file system uses NFS or some other networked FS you might have even more problems deleting files.  If the file you are trying to delete is being used by say, Apache or php then you might have to kill that process first.</p>

<h3>Creating Files in Restrictive Environments</h3>
<p>My research has been geared to try and make my code as robust as possible, I'm throwing everything but the kitchen sink into some of these functions because so many people are on such different types of servers.  To create a file in a restrictive environment is a fun excercise to take.. You can write a file using many different functions, but there are some tricks if they all fail.  One trick is instead of trying to "write" the data to the file, you can UPLOAD the data to the server and let PHP handle the file as if you used an upload form.  I like to use fsockopen to do it, as some installations have been setup to prevent this type of fake upload.</p>
<p>Then there are the various other hacks like using an ftp connection (if you know the user/pass) to send the file from php, using ssh from php, whatever is available on the hosts php installation.  In addition to those more involved workarounds you can often get around this problem by doing little hacks discussed at php.net in the comments for various functions.  Such as changing the umask, changing directories with chdir first, creating a temporary file using a function like tempfile and then renaming or copying the tempfile to your desired file which sometimes gives you the permissions needed to write to the location.</p>
<p>If the php installation is newer than you can also look into creating your own stream context to pass write the data direct.</p>


<h2>Stat Function</h2>
<p>I've created a stat function in php that goes farther than the normal stat function... Just give the function a file to stat, and it returns an array of information.  </p>
<pre>
function askapache_stat($filename) {
 clearstatcache();
 $ss=@stat($filename);
 if(!$ss) die("Couldnt stat {$filename}");
 $file_convert=array(0140000=&gt;&#039;ssocket&#039;,0120000=&gt;&#039;llink&#039;,0100000=&gt;&#039;-file&#039;,0060000=&gt;&#039;bblock&#039;,0040000=&gt;&#039;ddir&#039;,0020000=&gt;&#039;cchar&#039;,0010000=&gt;&#039;pfifo&#039;);
 $p=$ss[&#039;mode&#039;];
 $t=decoct($ss[&#039;mode&#039;] &amp; 0170000);
 $str = (array_key_exists(octdec($t),$file_convert)) ? $file_convert[octdec($t)]{0} : &#039;u&#039;;
 $str.=(($p&amp;0x0100)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0080)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0040)?(($p&amp;0x0800)?&#039;s&#039;:&#039;x&#039;):(($p&amp;0x0800)?&#039;S&#039;:&#039;-&#039;));
 $str.=(($p&amp;0x0020)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0010)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0008)?(($p&amp;0x0400)?&#039;s&#039;:&#039;x&#039;):(($p&amp;0x0400)?&#039;S&#039;:&#039;-&#039;));
 $str.=(($p&amp;0x0004)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0002)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0001)?(($p&amp;0x0200)?&#039;t&#039;:&#039;x&#039;):(($p&amp;0x0200)?&#039;T&#039;:&#039;-&#039;));
&nbsp;
 $s=array(
 &#039;perms&#039;=&gt;array(
  &#039;umask&#039;=&gt;sprintf("%04o",umask()),
  &#039;human&#039;=&gt;$str,
  &#039;octal1&#039;=&gt;sprintf("%o", ($ss[&#039;mode&#039;] &amp; 000777)),
  &#039;octal2&#039;=&gt;sprintf("0%o", 0777 &amp; $p),
  &#039;decimal&#039;=&gt;sprintf("%04o", $p),
  &#039;fileperms&#039;=&gt;@fileperms($filename),
  &#039;mode1&#039;=&gt;$p,
  &#039;mode2&#039;=&gt;$ss[&#039;mode&#039;]),
&nbsp;
 &#039;filetype&#039;=&gt;array(
  &#039;type&#039;=&gt;substr($file_convert[octdec($t)],1),
  &#039;type_octal&#039;=&gt;sprintf("%07o", octdec($t)),
  &#039;is_file&#039;=&gt;@is_file($filename),
  &#039;is_dir&#039;=&gt;@is_dir($filename),
  &#039;is_link&#039;=&gt;@is_link($filename),
  &#039;is_readable&#039;=&gt; @is_readable($filename),
  &#039;is_writable&#039;=&gt; @is_writable($filename)),
&nbsp;
 &#039;owner&#039;=&gt;array(
  &#039;fileowner&#039;=&gt;$ss[&#039;uid&#039;],
  &#039;filegroup&#039;=&gt;$ss[&#039;gid&#039;],
  &#039;owner_name&#039;=&gt;(function_exists(&#039;posix_getpwuid&#039;)) ? @reset(@posix_getpwuid($ss[&#039;uid&#039;])) : &#039;&#039;,
  &#039;group_name&#039;=&gt;(function_exists(&#039;posix_getgrgid&#039;)) ? @reset(@posix_getgrgid($ss[&#039;gid&#039;])) : &#039;&#039;),
&nbsp;
 &#039;file&#039;=&gt;array(
  &#039;filename&#039;=&gt;$filename,
  &#039;realpath&#039;=&gt;(@realpath($filename) != $filename) ? @realpath($filename) : &#039;&#039;,
  &#039;dirname&#039;=&gt;@dirname($filename),
  &#039;basename&#039;=&gt;@basename($filename)),
&nbsp;
 &#039;device&#039;=&gt;array(
  &#039;device&#039;=&gt;$ss[&#039;dev&#039;], //Device
  &#039;device_number&#039;=&gt;$ss[&#039;rdev&#039;], //Device number, if device.
  &#039;inode&#039;=&gt;$ss[&#039;ino&#039;], //File serial number
  &#039;link_count&#039;=&gt;$ss[&#039;nlink&#039;], //link count
  &#039;link_to&#039;=&gt;($s[&#039;type&#039;]==&#039;link&#039;) ? @readlink($filename) : &#039;&#039;),
&nbsp;
 &#039;size&#039;=&gt;array(
  &#039;size&#039;=&gt;$ss[&#039;size&#039;], //Size of file, in bytes.
  &#039;blocks&#039;=&gt;$ss[&#039;blocks&#039;], //Number 512-byte blocks allocated
  &#039;block_size&#039;=&gt; $ss[&#039;blksize&#039;]), //Optimal block size for I/O.
&nbsp;
 &#039;time&#039;=&gt;array(
  &#039;mtime&#039;=&gt;$ss[&#039;mtime&#039;], //Time of last modification
  &#039;atime&#039;=&gt;$ss[&#039;atime&#039;], //Time of last access.
  &#039;ctime&#039;=&gt;$ss[&#039;ctime&#039;], //Time of last status change
  &#039;accessed&#039;=&gt;@date(&#039;Y M D H:i:s&#039;,$ss[&#039;atime&#039;]),
  &#039;modified&#039;=&gt;@date(&#039;Y M D H:i:s&#039;,$ss[&#039;mtime&#039;]),
  &#039;created&#039;=&gt;@date(&#039;Y M D H:i:s&#039;,$ss[&#039;ctime&#039;])),
 );
&nbsp;
 clearstatcache();
 return $s;
}
</pre>


<h3>PHP Stat Function Output</h2>
<p>Example output, say from <code>print_r(askapache_stat( __FILE__ ) );</code></p>
<pre>
Array(
[perms] =&gt; Array
  (
  [umask] =&gt; 0022
  [human] =&gt; -rw-r--r--
  [octal1] =&gt; 644
  [octal2] =&gt; 0644
  [decimal] =&gt; 100644
  [fileperms] =&gt; 33188
  [mode1] =&gt; 33188
  [mode2] =&gt; 33188
  )
&nbsp;
[filetype] =&gt; Array
  (
  [type] =&gt; file
  [type_octal] =&gt; 0100000
  [is_file] =&gt; 1
  [is_dir] =&gt;
  [is_link] =&gt;
  [is_readable] =&gt; 1
  [is_writable] =&gt; 1
  )
&nbsp;
[owner] =&gt; Array
  (
  [fileowner] =&gt; 035483
  [filegroup] =&gt; 23472
  [owner_name] =&gt; askapache
  [group_name] =&gt; grp22558
  )
&nbsp;
[file] =&gt; Array
  (
  [filename] =&gt; /home/askapache/askapache-stat/public_html/ok/g.php
  [realpath] =&gt;
  [dirname] =&gt; /home/askapache/askapache-stat/public_html/ok
  [basename] =&gt; g.php
  )
&nbsp;
[device] =&gt; Array
  (
  [device] =&gt; 25
  [device_number] =&gt; 0
  [inode] =&gt; 92455020
  [link_count] =&gt; 1
  [link_to] =&gt;
  )
&nbsp;
[size] =&gt; Array
  (
  [size] =&gt; 2652
  [blocks] =&gt; 8
  [block_size] =&gt; 8192
  )
&nbsp;
[time] =&gt; Array
  (
  [mtime] =&gt; 1227685253
  [atime] =&gt; 1227685138
  [ctime] =&gt; 1227685253
  [accessed] =&gt; 2008 Nov Tue 23:38:58
  [modified] =&gt; 2008 Nov Tue 23:40:53
  [created] =&gt; 2008 Nov Tue 23:40:53
  )
)
</pre>






<h2><a id="chmod-0-to-7777"></a>Every Permission 0000 to 0777</h2>
<p><a class="IFL" href="http://uploads.askapache.com/2008/11/danger-chmod-screenshot.png"><img src="http://uploads.askapache.com/2008/11/danger-chmod-screenshot.png" alt="chmod, umask, file permissions test" title="chmod, umask, file permissions test" /></a>This shows what each numeric permission does to a REGULAR file.  I'll provide the code to do this below so you can do the same thing on your server.<br class="C" /></p>
<dl class="dlsm" style="border-right:1px solid #CCC;">
<dt><kbd>chmod 0</kbd></dt>
<dd><code>----------</code></dd>
<dt><kbd>chmod 1</kbd></dt>
<dd><code>---------x</code></dd>
<dt><kbd>chmod 2</kbd></dt>
<dd><code>--------w-</code></dd>
<dt><kbd>chmod 3</kbd></dt>
<dd><code>--------wx</code></dd>
<dt><kbd>chmod 4</kbd></dt>
<dd><code>-------r--</code></dd>
<dt><kbd>chmod 5</kbd></dt>
<dd><code>-------r-x</code></dd>
<dt><kbd>chmod 6</kbd></dt>
<dd><code>-------rw-</code></dd>
<dt><kbd>chmod 7</kbd></dt>
<dd><code>-------rwx</code></dd>
<dt><kbd>chmod 10</kbd></dt>
<dd><code>------x---</code></dd>
<dt><kbd>chmod 11</kbd></dt>
<dd><code>------x--x</code></dd>
<dt><kbd>chmod 12</kbd></dt>
<dd><code>------x-w-</code></dd>
<dt><kbd>chmod 13</kbd></dt>
<dd><code>------x-wx</code></dd>
<dt><kbd>chmod 14</kbd></dt>
<dd><code>------xr--</code></dd>
<dt><kbd>chmod 15</kbd></dt>
<dd><code>------xr-x</code></dd>
<dt><kbd>chmod 16</kbd></dt>
<dd><code>------xrw-</code></dd>
<dt><kbd>chmod 17</kbd></dt>
<dd><code>------xrwx</code></dd>
<dt><kbd>chmod 20</kbd></dt>
<dd><code>-----w----</code></dd>
<dt><kbd>chmod 21</kbd></dt>
<dd><code>-----w---x</code></dd>
<dt><kbd>chmod 22</kbd></dt>
<dd><code>-----w--w-</code></dd>
<dt><kbd>chmod 23</kbd></dt>
<dd><code>-----w--wx</code></dd>
<dt><kbd>chmod 24</kbd></dt>
<dd><code>-----w-r--</code></dd>
<dt><kbd>chmod 25</kbd></dt>
<dd><code>-----w-r-x</code></dd>
<dt><kbd>chmod 26</kbd></dt>
<dd><code>-----w-rw-</code></dd>
<dt><kbd>chmod 27</kbd></dt>
<dd><code>-----w-rwx</code></dd>
<dt><kbd>chmod 30</kbd></dt>
<dd><code>-----wx---</code></dd>
<dt><kbd>chmod 31</kbd></dt>
<dd><code>-----wx--x</code></dd>
<dt><kbd>chmod 32</kbd></dt>
<dd><code>-----wx-w-</code></dd>
<dt><kbd>chmod 33</kbd></dt>
<dd><code>-----wx-wx</code></dd>
<dt><kbd>chmod 34</kbd></dt>
<dd><code>-----wxr--</code></dd>
<dt><kbd>chmod 35</kbd></dt>
<dd><code>-----wxr-x</code></dd>
<dt><kbd>chmod 36</kbd></dt>
<dd><code>-----wxrw-</code></dd>
<dt><kbd>chmod 37</kbd></dt>
<dd><code>-----wxrwx</code></dd>
<dt><kbd>chmod 40</kbd></dt>
<dd><code>----r-----</code></dd>
<dt><kbd>chmod 41</kbd></dt>
<dd><code>----r----x</code></dd>
<dt><kbd>chmod 42</kbd></dt>
<dd><code>----r---w-</code></dd>
<dt><kbd>chmod 43</kbd></dt>
<dd><code>----r---wx</code></dd>
<dt><kbd>chmod 44</kbd></dt>
<dd><code>----r--r--</code></dd>
<dt><kbd>chmod 45</kbd></dt>
<dd><code>----r--r-x</code></dd>
<dt><kbd>chmod 46</kbd></dt>
<dd><code>----r--rw-</code></dd>
<dt><kbd>chmod 47</kbd></dt>
<dd><code>----r--rwx</code></dd>
<dt><kbd>chmod 50</kbd></dt>
<dd><code>----r-x---</code></dd>
<dt><kbd>chmod 51</kbd></dt>
<dd><code>----r-x--x</code></dd>
<dt><kbd>chmod 52</kbd></dt>
<dd><code>----r-x-w-</code></dd>
<dt><kbd>chmod 53</kbd></dt>
<dd><code>----r-x-wx</code></dd>
<dt><kbd>chmod 54</kbd></dt>
<dd><code>----r-xr--</code></dd>
<dt><kbd>chmod 55</kbd></dt>
<dd><code>----r-xr-x</code></dd>
<dt><kbd>chmod 56</kbd></dt>
<dd><code>----r-xrw-</code></dd>
<dt><kbd>chmod 57</kbd></dt>
<dd><code>----r-xrwx</code></dd>
<dt><kbd>chmod 60</kbd></dt>
<dd><code>----rw----</code></dd>
<dt><kbd>chmod 61</kbd></dt>
<dd><code>----rw---x</code></dd>
<dt><kbd>chmod 62</kbd></dt>
<dd><code>----rw--w-</code></dd>
<dt><kbd>chmod 63</kbd></dt>
<dd><code>----rw--wx</code></dd>
<dt><kbd>chmod 64</kbd></dt>
<dd><code>----rw-r--</code></dd>
<dt><kbd>chmod 65</kbd></dt>
<dd><code>----rw-r-x</code></dd>
<dt><kbd>chmod 66</kbd></dt>
<dd><code>----rw-rw-</code></dd>
<dt><kbd>chmod 67</kbd></dt>
<dd><code>----rw-rwx</code></dd>
<dt><kbd>chmod 70</kbd></dt>
<dd><code>----rwx---</code></dd>
<dt><kbd>chmod 71</kbd></dt>
<dd><code>----rwx--x</code></dd>
<dt><kbd>chmod 72</kbd></dt>
<dd><code>----rwx-w-</code></dd>
<dt><kbd>chmod 73</kbd></dt>
<dd><code>----rwx-wx</code></dd>
<dt><kbd>chmod 74</kbd></dt>
<dd><code>----rwxr--</code></dd>
<dt><kbd>chmod 75</kbd></dt>
<dd><code>----rwxr-x</code></dd>
<dt><kbd>chmod 76</kbd></dt>
<dd><code>----rwxrw-</code></dd>
<dt><kbd>chmod 77</kbd></dt>
<dd><code>----rwxrwx</code></dd>
<dt><kbd>chmod 100</kbd></dt>
<dd><code>---x------</code></dd>
<dt><kbd>chmod 101</kbd></dt>
<dd><code>---x-----x</code></dd>
<dt><kbd>chmod 102</kbd></dt>
<dd><code>---x----w-</code></dd>
<dt><kbd>chmod 103</kbd></dt>
<dd><code>---x----wx</code></dd>
<dt><kbd>chmod 104</kbd></dt>
<dd><code>---x---r--</code></dd>
<dt><kbd>chmod 105</kbd></dt>
<dd><code>---x---r-x</code></dd>
<dt><kbd>chmod 106</kbd></dt>
<dd><code>---x---rw-</code></dd>
<dt><kbd>chmod 107</kbd></dt>
<dd><code>---x---rwx</code></dd>
<dt><kbd>chmod 110</kbd></dt>
<dd><code>---x--x---</code></dd>
<dt><kbd>chmod 111</kbd></dt>
<dd><code>---x--x--x</code></dd>
<dt><kbd>chmod 112</kbd></dt>
<dd><code>---x--x-w-</code></dd>
<dt><kbd>chmod 113</kbd></dt>
<dd><code>---x--x-wx</code></dd>
<dt><kbd>chmod 114</kbd></dt>
<dd><code>---x--xr--</code></dd>
<dt><kbd>chmod 115</kbd></dt>
<dd><code>---x--xr-x</code></dd>
<dt><kbd>chmod 116</kbd></dt>
<dd><code>---x--xrw-</code></dd>
<dt><kbd>chmod 117</kbd></dt>
<dd><code>---x--xrwx</code></dd>
<dt><kbd>chmod 120</kbd></dt>
<dd><code>---x-w----</code></dd>
<dt><kbd>chmod 121</kbd></dt>
<dd><code>---x-w---x</code></dd>
<dt><kbd>chmod 122</kbd></dt>
<dd><code>---x-w--w-</code></dd>
<dt><kbd>chmod 123</kbd></dt>
<dd><code>---x-w--wx</code></dd>
<dt><kbd>chmod 124</kbd></dt>
<dd><code>---x-w-r--</code></dd>
<dt><kbd>chmod 125</kbd></dt>
<dd><code>---x-w-r-x</code></dd>
<dt><kbd>chmod 126</kbd></dt>
<dd><code>---x-w-rw-</code></dd>
<dt><kbd>chmod 127</kbd></dt>
<dd><code>---x-w-rwx</code></dd>
<dt><kbd>chmod 130</kbd></dt>
<dd><code>---x-wx---</code></dd>
<dt><kbd>chmod 131</kbd></dt>
<dd><code>---x-wx--x</code></dd>
<dt><kbd>chmod 132</kbd></dt>
<dd><code>---x-wx-w-</code></dd>
<dt><kbd>chmod 133</kbd></dt>
<dd><code>---x-wx-wx</code></dd>
<dt><kbd>chmod 134</kbd></dt>
<dd><code>---x-wxr--</code></dd>
<dt><kbd>chmod 135</kbd></dt>
<dd><code>---x-wxr-x</code></dd>
<dt><kbd>chmod 136</kbd></dt>
<dd><code>---x-wxrw-</code></dd>
<dt><kbd>chmod 137</kbd></dt>
<dd><code>---x-wxrwx</code></dd>
<dt><kbd>chmod 140</kbd></dt>
<dd><code>---xr-----</code></dd>
<dt><kbd>chmod 141</kbd></dt>
<dd><code>---xr----x</code></dd>
<dt><kbd>chmod 142</kbd></dt>
<dd><code>---xr---w-</code></dd>
<dt><kbd>chmod 143</kbd></dt>
<dd><code>---xr---wx</code></dd>
<dt><kbd>chmod 144</kbd></dt>
<dd><code>---xr--r--</code></dd>
<dt><kbd>chmod 145</kbd></dt>
<dd><code>---xr--r-x</code></dd>
<dt><kbd>chmod 146</kbd></dt>
<dd><code>---xr--rw-</code></dd>
<dt><kbd>chmod 147</kbd></dt>
<dd><code>---xr--rwx</code></dd>
<dt><kbd>chmod 150</kbd></dt>
<dd><code>---xr-x---</code></dd>
<dt><kbd>chmod 151</kbd></dt>
<dd><code>---xr-x--x</code></dd>
<dt><kbd>chmod 152</kbd></dt>
<dd><code>---xr-x-w-</code></dd>
<dt><kbd>chmod 153</kbd></dt>
<dd><code>---xr-x-wx</code></dd>
<dt><kbd>chmod 154</kbd></dt>
<dd><code>---xr-xr--</code></dd>
<dt><kbd>chmod 155</kbd></dt>
<dd><code>---xr-xr-x</code></dd>
<dt><kbd>chmod 156</kbd></dt>
<dd><code>---xr-xrw-</code></dd>
<dt><kbd>chmod 157</kbd></dt>
<dd><code>---xr-xrwx</code></dd>
<dt><kbd>chmod 160</kbd></dt>
<dd><code>---xrw----</code></dd>
<dt><kbd>chmod 161</kbd></dt>
<dd><code>---xrw---x</code></dd>
<dt><kbd>chmod 162</kbd></dt>
<dd><code>---xrw--w-</code></dd>
<dt><kbd>chmod 163</kbd></dt>
<dd><code>---xrw--wx</code></dd>
<dt><kbd>chmod 164</kbd></dt>
<dd><code>---xrw-r--</code></dd>
<dt><kbd>chmod 165</kbd></dt>
<dd><code>---xrw-r-x</code></dd>
<dt><kbd>chmod 166</kbd></dt>
<dd><code>---xrw-rw-</code></dd>
<dt><kbd>chmod 167</kbd></dt>
<dd><code>---xrw-rwx</code></dd>
<dt><kbd>chmod 170</kbd></dt>
<dd><code>---xrwx---</code></dd>
<dt><kbd>chmod 171</kbd></dt>
<dd><code>---xrwx--x</code></dd>
<dt><kbd>chmod 172</kbd></dt>
<dd><code>---xrwx-w-</code></dd>
<dt><kbd>chmod 173</kbd></dt>
<dd><code>---xrwx-wx</code></dd>
<dt><kbd>chmod 174</kbd></dt>
<dd><code>---xrwxr--</code></dd>
<dt><kbd>chmod 175</kbd></dt>
<dd><code>---xrwxr-x</code></dd>
<dt><kbd>chmod 176</kbd></dt>
<dd><code>---xrwxrw-</code></dd>
<dt><kbd>chmod 177</kbd></dt>
<dd><code>---xrwxrwx</code></dd>
<dt><kbd>chmod 200</kbd></dt>
<dd><code>--w-------</code></dd>
<dt><kbd>chmod 201</kbd></dt>
<dd><code>--w------x</code></dd>
<dt><kbd>chmod 202</kbd></dt>
<dd><code>--w-----w-</code></dd>
<dt><kbd>chmod 203</kbd></dt>
<dd><code>--w-----wx</code></dd>
<dt><kbd>chmod 204</kbd></dt>
<dd><code>--w----r--</code></dd>
<dt><kbd>chmod 205</kbd></dt>
<dd><code>--w----r-x</code></dd>
<dt><kbd>chmod 206</kbd></dt>
<dd><code>--w----rw-</code></dd>
<dt><kbd>chmod 207</kbd></dt>
<dd><code>--w----rwx</code></dd>
<dt><kbd>chmod 210</kbd></dt>
<dd><code>--w---x---</code></dd>
<dt><kbd>chmod 211</kbd></dt>
<dd><code>--w---x--x</code></dd>
<dt><kbd>chmod 212</kbd></dt>
<dd><code>--w---x-w-</code></dd>
<dt><kbd>chmod 213</kbd></dt>
<dd><code>--w---x-wx</code></dd>
<dt><kbd>chmod 214</kbd></dt>
<dd><code>--w---xr--</code></dd>
<dt><kbd>chmod 215</kbd></dt>
<dd><code>--w---xr-x</code></dd>
<dt><kbd>chmod 216</kbd></dt>
<dd><code>--w---xrw-</code></dd>
<dt><kbd>chmod 217</kbd></dt>
<dd><code>--w---xrwx</code></dd>
<dt><kbd>chmod 220</kbd></dt>
<dd><code>--w--w----</code></dd>
<dt><kbd>chmod 221</kbd></dt>
<dd><code>--w--w---x</code></dd>
<dt><kbd>chmod 222</kbd></dt>
<dd><code>--w--w--w-</code></dd>
<dt><kbd>chmod 223</kbd></dt>
<dd><code>--w--w--wx</code></dd>
<dt><kbd>chmod 224</kbd></dt>
<dd><code>--w--w-r--</code></dd>
<dt><kbd>chmod 225</kbd></dt>
<dd><code>--w--w-r-x</code></dd>
<dt><kbd>chmod 226</kbd></dt>
<dd><code>--w--w-rw-</code></dd>
<dt><kbd>chmod 227</kbd></dt>
<dd><code>--w--w-rwx</code></dd>
<dt><kbd>chmod 230</kbd></dt>
<dd><code>--w--wx---</code></dd>
<dt><kbd>chmod 231</kbd></dt>
<dd><code>--w--wx--x</code></dd>
<dt><kbd>chmod 232</kbd></dt>
<dd><code>--w--wx-w-</code></dd>
<dt><kbd>chmod 233</kbd></dt>
<dd><code>--w--wx-wx</code></dd>
<dt><kbd>chmod 234</kbd></dt>
<dd><code>--w--wxr--</code></dd>
<dt><kbd>chmod 235</kbd></dt>
<dd><code>--w--wxr-x</code></dd>
<dt><kbd>chmod 236</kbd></dt>
<dd><code>--w--wxrw-</code></dd>
<dt><kbd>chmod 237</kbd></dt>
<dd><code>--w--wxrwx</code></dd>
<dt><kbd>chmod 240</kbd></dt>
<dd><code>--w-r-----</code></dd>
<dt><kbd>chmod 241</kbd></dt>
<dd><code>--w-r----x</code></dd>
<dt><kbd>chmod 242</kbd></dt>
<dd><code>--w-r---w-</code></dd>
<dt><kbd>chmod 243</kbd></dt>
<dd><code>--w-r---wx</code></dd>
<dt><kbd>chmod 244</kbd></dt>
<dd><code>--w-r--r--</code></dd>
<dt><kbd>chmod 245</kbd></dt>
<dd><code>--w-r--r-x</code></dd>
<dt><kbd>chmod 246</kbd></dt>
<dd><code>--w-r--rw-</code></dd>
<dt><kbd>chmod 247</kbd></dt>
<dd><code>--w-r--rwx</code></dd>
<dt><kbd>chmod 250</kbd></dt>
<dd><code>--w-r-x---</code></dd>
<dt><kbd>chmod 251</kbd></dt>
<dd><code>--w-r-x--x</code></dd>
<dt><kbd>chmod 252</kbd></dt>
<dd><code>--w-r-x-w-</code></dd>
<dt><kbd>chmod 253</kbd></dt>
<dd><code>--w-r-x-wx</code></dd>
<dt><kbd>chmod 254</kbd></dt>
<dd><code>--w-r-xr--</code></dd>
<dt><kbd>chmod 255</kbd></dt>
<dd><code>--w-r-xr-x</code></dd>
<dt><kbd>chmod 256</kbd></dt>
<dd><code>--w-r-xrw-</code></dd>
<dt><kbd>chmod 257</kbd></dt>
<dd><code>--w-r-xrwx</code></dd>
<dt><kbd>chmod 260</kbd></dt>
<dd><code>--w-rw----</code></dd>
<dt><kbd>chmod 261</kbd></dt>
<dd><code>--w-rw---x</code></dd>
<dt><kbd>chmod 262</kbd></dt>
<dd><code>--w-rw--w-</code></dd>
<dt><kbd>chmod 263</kbd></dt>
<dd><code>--w-rw--wx</code></dd>
<dt><kbd>chmod 264</kbd></dt>
<dd><code>--w-rw-r--</code></dd>
<dt><kbd>chmod 265</kbd></dt>
<dd><code>--w-rw-r-x</code></dd>
<dt><kbd>chmod 266</kbd></dt>
<dd><code>--w-rw-rw-</code></dd>
<dt><kbd>chmod 267</kbd></dt>
<dd><code>--w-rw-rwx</code></dd>
<dt><kbd>chmod 270</kbd></dt>
<dd><code>--w-rwx---</code></dd>
<dt><kbd>chmod 271</kbd></dt>
<dd><code>--w-rwx--x</code></dd>
<dt><kbd>chmod 272</kbd></dt>
<dd><code>--w-rwx-w-</code></dd>
<dt><kbd>chmod 273</kbd></dt>
<dd><code>--w-rwx-wx</code></dd>
<dt><kbd>chmod 274</kbd></dt>
<dd><code>--w-rwxr--</code></dd>
<dt><kbd>chmod 275</kbd></dt>
<dd><code>--w-rwxr-x</code></dd>
<dt><kbd>chmod 276</kbd></dt>
<dd><code>--w-rwxrw-</code></dd>
<dt><kbd>chmod 277</kbd></dt>
<dd><code>--w-rwxrwx</code></dd>
<dt><kbd>chmod 300</kbd></dt>
<dd><code>--wx------</code></dd>
<dt><kbd>chmod 301</kbd></dt>
<dd><code>--wx-----x</code></dd>
<dt><kbd>chmod 302</kbd></dt>
<dd><code>--wx----w-</code></dd>
<dt><kbd>chmod 303</kbd></dt>
<dd><code>--wx----wx</code></dd>
<dt><kbd>chmod 304</kbd></dt>
<dd><code>--wx---r--</code></dd>
<dt><kbd>chmod 305</kbd></dt>
<dd><code>--wx---r-x</code></dd>
<dt><kbd>chmod 306</kbd></dt>
<dd><code>--wx---rw-</code></dd>
<dt><kbd>chmod 307</kbd></dt>
<dd><code>--wx---rwx</code></dd>
<dt><kbd>chmod 310</kbd></dt>
<dd><code>--wx--x---</code></dd>
<dt><kbd>chmod 311</kbd></dt>
<dd><code>--wx--x--x</code></dd>
<dt><kbd>chmod 312</kbd></dt>
<dd><code>--wx--x-w-</code></dd>
<dt><kbd>chmod 313</kbd></dt>
<dd><code>--wx--x-wx</code></dd>
<dt><kbd>chmod 314</kbd></dt>
<dd><code>--wx--xr--</code></dd>
<dt><kbd>chmod 315</kbd></dt>
<dd><code>--wx--xr-x</code></dd>
<dt><kbd>chmod 316</kbd></dt>
<dd><code>--wx--xrw-</code></dd>
<dt><kbd>chmod 317</kbd></dt>
<dd><code>--wx--xrwx</code></dd>
<dt><kbd>chmod 320</kbd></dt>
<dd><code>--wx-w----</code></dd>
<dt><kbd>chmod 321</kbd></dt>
<dd><code>--wx-w---x</code></dd>
<dt><kbd>chmod 322</kbd></dt>
<dd><code>--wx-w--w-</code></dd>
<dt><kbd>chmod 323</kbd></dt>
<dd><code>--wx-w--wx</code></dd>
<dt><kbd>chmod 324</kbd></dt>
<dd><code>--wx-w-r--</code></dd>
<dt><kbd>chmod 325</kbd></dt>
<dd><code>--wx-w-r-x</code></dd>
<dt><kbd>chmod 326</kbd></dt>
<dd><code>--wx-w-rw-</code></dd>
<dt><kbd>chmod 327</kbd></dt>
<dd><code>--wx-w-rwx</code></dd>
<dt><kbd>chmod 330</kbd></dt>
<dd><code>--wx-wx---</code></dd>
<dt><kbd>chmod 331</kbd></dt>
<dd><code>--wx-wx--x</code></dd>
<dt><kbd>chmod 332</kbd></dt>
<dd><code>--wx-wx-w-</code></dd>
<dt><kbd>chmod 333</kbd></dt>
<dd><code>--wx-wx-wx</code></dd>
<dt><kbd>chmod 334</kbd></dt>
<dd><code>--wx-wxr--</code></dd>
<dt><kbd>chmod 335</kbd></dt>
<dd><code>--wx-wxr-x</code></dd>
<dt><kbd>chmod 336</kbd></dt>
<dd><code>--wx-wxrw-</code></dd>
<dt><kbd>chmod 337</kbd></dt>
<dd><code>--wx-wxrwx</code></dd>
<dt><kbd>chmod 340</kbd></dt>
<dd><code>--wxr-----</code></dd>
<dt><kbd>chmod 341</kbd></dt>
<dd><code>--wxr----x</code></dd>
<dt><kbd>chmod 342</kbd></dt>
<dd><code>--wxr---w-</code></dd>
<dt><kbd>chmod 343</kbd></dt>
<dd><code>--wxr---wx</code></dd>
<dt><kbd>chmod 344</kbd></dt>
<dd><code>--wxr--r--</code></dd>
<dt><kbd>chmod 345</kbd></dt>
<dd><code>--wxr--r-x</code></dd>
<dt><kbd>chmod 346</kbd></dt>
<dd><code>--wxr--rw-</code></dd>
<dt><kbd>chmod 347</kbd></dt>
<dd><code>--wxr--rwx</code></dd>
<dt><kbd>chmod 350</kbd></dt>
<dd><code>--wxr-x---</code></dd>
<dt><kbd>chmod 351</kbd></dt>
<dd><code>--wxr-x--x</code></dd>
<dt><kbd>chmod 352</kbd></dt>
<dd><code>--wxr-x-w-</code></dd>
<dt><kbd>chmod 353</kbd></dt>
<dd><code>--wxr-x-wx</code></dd>
<dt><kbd>chmod 354</kbd></dt>
<dd><code>--wxr-xr--</code></dd>
<dt><kbd>chmod 355</kbd></dt>
<dd><code>--wxr-xr-x</code></dd>
<dt><kbd>chmod 356</kbd></dt>
<dd><code>--wxr-xrw-</code></dd>
<dt><kbd>chmod 357</kbd></dt>
<dd><code>--wxr-xrwx</code></dd>
<dt><kbd>chmod 360</kbd></dt>
<dd><code>--wxrw----</code></dd>
<dt><kbd>chmod 361</kbd></dt>
<dd><code>--wxrw---x</code></dd>
<dt><kbd>chmod 362</kbd></dt>
<dd><code>--wxrw--w-</code></dd>
<dt><kbd>chmod 363</kbd></dt>
<dd><code>--wxrw--wx</code></dd>
<dt><kbd>chmod 364</kbd></dt>
<dd><code>--wxrw-r--</code></dd>
<dt><kbd>chmod 365</kbd></dt>
<dd><code>--wxrw-r-x</code></dd>
<dt><kbd>chmod 366</kbd></dt>
<dd><code>--wxrw-rw-</code></dd>
<dt><kbd>chmod 367</kbd></dt>
<dd><code>--wxrw-rwx</code></dd>
<dt><kbd>chmod 370</kbd></dt>
<dd><code>--wxrwx---</code></dd>
<dt><kbd>chmod 371</kbd></dt>
<dd><code>--wxrwx--x</code></dd>
<dt><kbd>chmod 372</kbd></dt>
<dd><code>--wxrwx-w-</code></dd>
<dt><kbd>chmod 373</kbd></dt>
<dd><code>--wxrwx-wx</code></dd>
<dt><kbd>chmod 374</kbd></dt>
<dd><code>--wxrwxr--</code></dd>
<dt><kbd>chmod 375</kbd></dt>
<dd><code>--wxrwxr-x</code></dd>
<dt><kbd>chmod 376</kbd></dt>
<dd><code>--wxrwxrw-</code></dd>
<dt><kbd>chmod 377</kbd></dt>
<dd><code>--wxrwxrwx</code></dd>
<dt><kbd>chmod 400</kbd></dt>
<dd><code>-r--------</code></dd>
<dt><kbd>chmod 401</kbd></dt>
<dd><code>-r-------x</code></dd>
<dt><kbd>chmod 402</kbd></dt>
<dd><code>-r------w-</code></dd>
<dt><kbd>chmod 403</kbd></dt>
<dd><code>-r------wx</code></dd>
<dt><kbd>chmod 404</kbd></dt>
<dd><code>-r-----r--</code></dd>
<dt><kbd>chmod 405</kbd></dt>
<dd><code>-r-----r-x</code></dd>
<dt><kbd>chmod 406</kbd></dt>
<dd><code>-r-----rw-</code></dd>
<dt><kbd>chmod 407</kbd></dt>
<dd><code>-r-----rwx</code></dd>
<dt><kbd>chmod 410</kbd></dt>
<dd><code>-r----x---</code></dd>
<dt><kbd>chmod 411</kbd></dt>
<dd><code>-r----x--x</code></dd>
<dt><kbd>chmod 412</kbd></dt>
<dd><code>-r----x-w-</code></dd>
<dt><kbd>chmod 413</kbd></dt>
<dd><code>-r----x-wx</code></dd>
<dt><kbd>chmod 414</kbd></dt>
<dd><code>-r----xr--</code></dd>
<dt><kbd>chmod 415</kbd></dt>
<dd><code>-r----xr-x</code></dd>
<dt><kbd>chmod 416</kbd></dt>
<dd><code>-r----xrw-</code></dd>
<dt><kbd>chmod 417</kbd></dt>
<dd><code>-r----xrwx</code></dd>
<dt><kbd>chmod 420</kbd></dt>
<dd><code>-r---w----</code></dd>
<dt><kbd>chmod 421</kbd></dt>
<dd><code>-r---w---x</code></dd>
<dt><kbd>chmod 422</kbd></dt>
<dd><code>-r---w--w-</code></dd>
<dt><kbd>chmod 423</kbd></dt>
<dd><code>-r---w--wx</code></dd>
<dt><kbd>chmod 424</kbd></dt>
<dd><code>-r---w-r--</code></dd>
<dt><kbd>chmod 425</kbd></dt>
<dd><code>-r---w-r-x</code></dd>
<dt><kbd>chmod 426</kbd></dt>
<dd><code>-r---w-rw-</code></dd>
<dt><kbd>chmod 427</kbd></dt>
<dd><code>-r---w-rwx</code></dd>
<dt><kbd>chmod 430</kbd></dt>
<dd><code>-r---wx---</code></dd>
<dt><kbd>chmod 431</kbd></dt>
<dd><code>-r---wx--x</code></dd>
<dt><kbd>chmod 432</kbd></dt>
<dd><code>-r---wx-w-</code></dd>
<dt><kbd>chmod 433</kbd></dt>
<dd><code>-r---wx-wx</code></dd>
<dt><kbd>chmod 434</kbd></dt>
<dd><code>-r---wxr--</code></dd>
<dt><kbd>chmod 435</kbd></dt>
<dd><code>-r---wxr-x</code></dd>
<dt><kbd>chmod 436</kbd></dt>
<dd><code>-r---wxrw-</code></dd>
<dt><kbd>chmod 437</kbd></dt>
<dd><code>-r---wxrwx</code></dd>
<dt><kbd>chmod 440</kbd></dt>
<dd><code>-r--r-----</code></dd>
<dt><kbd>chmod 441</kbd></dt>
<dd><code>-r--r----x</code></dd>
<dt><kbd>chmod 442</kbd></dt>
<dd><code>-r--r---w-</code></dd>
<dt><kbd>chmod 443</kbd></dt>
<dd><code>-r--r---wx</code></dd>
<dt><kbd>chmod 444</kbd></dt>
<dd><code>-r--r--r--</code></dd>
<dt><kbd>chmod 445</kbd></dt>
<dd><code>-r--r--r-x</code></dd>
<dt><kbd>chmod 446</kbd></dt>
<dd><code>-r--r--rw-</code></dd>
<dt><kbd>chmod 447</kbd></dt>
<dd><code>-r--r--rwx</code></dd>
<dt><kbd>chmod 450</kbd></dt>
<dd><code>-r--r-x---</code></dd>
<dt><kbd>chmod 451</kbd></dt>
<dd><code>-r--r-x--x</code></dd>
<dt><kbd>chmod 452</kbd></dt>
<dd><code>-r--r-x-w-</code></dd>
<dt><kbd>chmod 453</kbd></dt>
<dd><code>-r--r-x-wx</code></dd>
<dt><kbd>chmod 454</kbd></dt>
<dd><code>-r--r-xr--</code></dd>
<dt><kbd>chmod 455</kbd></dt>
<dd><code>-r--r-xr-x</code></dd>
<dt><kbd>chmod 456</kbd></dt>
<dd><code>-r--r-xrw-</code></dd>
<dt><kbd>chmod 457</kbd></dt>
<dd><code>-r--r-xrwx</code></dd>
<dt><kbd>chmod 460</kbd></dt>
<dd><code>-r--rw----</code></dd>
<dt><kbd>chmod 461</kbd></dt>
<dd><code>-r--rw---x</code></dd>
<dt><kbd>chmod 462</kbd></dt>
<dd><code>-r--rw--w-</code></dd>
<dt><kbd>chmod 463</kbd></dt>
<dd><code>-r--rw--wx</code></dd>
<dt><kbd>chmod 464</kbd></dt>
<dd><code>-r--rw-r--</code></dd>
<dt><kbd>chmod 465</kbd></dt>
<dd><code>-r--rw-r-x</code></dd>
<dt><kbd>chmod 466</kbd></dt>
<dd><code>-r--rw-rw-</code></dd>
<dt><kbd>chmod 467</kbd></dt>
<dd><code>-r--rw-rwx</code></dd>
<dt><kbd>chmod 470</kbd></dt>
<dd><code>-r--rwx---</code></dd>
<dt><kbd>chmod 471</kbd></dt>
<dd><code>-r--rwx--x</code></dd>
<dt><kbd>chmod 472</kbd></dt>
<dd><code>-r--rwx-w-</code></dd>
<dt><kbd>chmod 473</kbd></dt>
<dd><code>-r--rwx-wx</code></dd>
<dt><kbd>chmod 474</kbd></dt>
<dd><code>-r--rwxr--</code></dd>
<dt><kbd>chmod 475</kbd></dt>
<dd><code>-r--rwxr-x</code></dd>
<dt><kbd>chmod 476</kbd></dt>
<dd><code>-r--rwxrw-</code></dd>
<dt><kbd>chmod 477</kbd></dt>
<dd><code>-r--rwxrwx</code></dd>
<dt><kbd>chmod 500</kbd></dt>
<dd><code>-r-x------</code></dd>
<dt><kbd>chmod 501</kbd></dt>
<dd><code>-r-x-----x</code></dd>
<dt><kbd>chmod 502</kbd></dt>
<dd><code>-r-x----w-</code></dd>
<dt><kbd>chmod 503</kbd></dt>
<dd><code>-r-x----wx</code></dd>
<dt><kbd>chmod 504</kbd></dt>
<dd><code>-r-x---r--</code></dd>
<dt><kbd>chmod 505</kbd></dt>
<dd><code>-r-x---r-x</code></dd>
<dt><kbd>chmod 506</kbd></dt>
<dd><code>-r-x---rw-</code></dd>
<dt><kbd>chmod 507</kbd></dt>
<dd><code>-r-x---rwx</code></dd>
<dt><kbd>chmod 510</kbd></dt>
<dd><code>-r-x--x---</code></dd>
<dt><kbd>chmod 511</kbd></dt>
<dd><code>-r-x--x--x</code></dd>
<dt><kbd>chmod 512</kbd></dt>
<dd><code>-r-x--x-w-</code></dd>
<dt><kbd>chmod 513</kbd></dt>
<dd><code>-r-x--x-wx</code></dd>
<dt><kbd>chmod 514</kbd></dt>
<dd><code>-r-x--xr--</code></dd>
<dt><kbd>chmod 515</kbd></dt>
<dd><code>-r-x--xr-x</code></dd>
<dt><kbd>chmod 516</kbd></dt>
<dd><code>-r-x--xrw-</code></dd>
<dt><kbd>chmod 517</kbd></dt>
<dd><code>-r-x--xrwx</code></dd>
<dt><kbd>chmod 520</kbd></dt>
<dd><code>-r-x-w----</code></dd>
<dt><kbd>chmod 521</kbd></dt>
<dd><code>-r-x-w---x</code></dd>
<dt><kbd>chmod 522</kbd></dt>
<dd><code>-r-x-w--w-</code></dd>
<dt><kbd>chmod 523</kbd></dt>
<dd><code>-r-x-w--wx</code></dd>
<dt><kbd>chmod 524</kbd></dt>
<dd><code>-r-x-w-r--</code></dd>
<dt><kbd>chmod 525</kbd></dt>
<dd><code>-r-x-w-r-x</code></dd>
<dt><kbd>chmod 526</kbd></dt>
<dd><code>-r-x-w-rw-</code></dd>
<dt><kbd>chmod 527</kbd></dt>
<dd><code>-r-x-w-rwx</code></dd>
<dt><kbd>chmod 530</kbd></dt>
<dd><code>-r-x-wx---</code></dd>
<dt><kbd>chmod 531</kbd></dt>
<dd><code>-r-x-wx--x</code></dd>
<dt><kbd>chmod 532</kbd></dt>
<dd><code>-r-x-wx-w-</code></dd>
<dt><kbd>chmod 533</kbd></dt>
<dd><code>-r-x-wx-wx</code></dd>
<dt><kbd>chmod 534</kbd></dt>
<dd><code>-r-x-wxr--</code></dd>
<dt><kbd>chmod 535</kbd></dt>
<dd><code>-r-x-wxr-x</code></dd>
<dt><kbd>chmod 536</kbd></dt>
<dd><code>-r-x-wxrw-</code></dd>
<dt><kbd>chmod 537</kbd></dt>
<dd><code>-r-x-wxrwx</code></dd>
<dt><kbd>chmod 540</kbd></dt>
<dd><code>-r-xr-----</code></dd>
<dt><kbd>chmod 541</kbd></dt>
<dd><code>-r-xr----x</code></dd>
<dt><kbd>chmod 542</kbd></dt>
<dd><code>-r-xr---w-</code></dd>
<dt><kbd>chmod 543</kbd></dt>
<dd><code>-r-xr---wx</code></dd>
<dt><kbd>chmod 544</kbd></dt>
<dd><code>-r-xr--r--</code></dd>
<dt><kbd>chmod 545</kbd></dt>
<dd><code>-r-xr--r-x</code></dd>
<dt><kbd>chmod 546</kbd></dt>
<dd><code>-r-xr--rw-</code></dd>
<dt><kbd>chmod 547</kbd></dt>
<dd><code>-r-xr--rwx</code></dd>
<dt><kbd>chmod 550</kbd></dt>
<dd><code>-r-xr-x---</code></dd>
<dt><kbd>chmod 551</kbd></dt>
<dd><code>-r-xr-x--x</code></dd>
<dt><kbd>chmod 552</kbd></dt>
<dd><code>-r-xr-x-w-</code></dd>
<dt><kbd>chmod 553</kbd></dt>
<dd><code>-r-xr-x-wx</code></dd>
<dt><kbd>chmod 554</kbd></dt>
<dd><code>-r-xr-xr--</code></dd>
<dt><kbd>chmod 555</kbd></dt>
<dd><code>-r-xr-xr-x</code></dd>
<dt><kbd>chmod 556</kbd></dt>
<dd><code>-r-xr-xrw-</code></dd>
<dt><kbd>chmod 557</kbd></dt>
<dd><code>-r-xr-xrwx</code></dd>
<dt><kbd>chmod 560</kbd></dt>
<dd><code>-r-xrw----</code></dd>
<dt><kbd>chmod 561</kbd></dt>
<dd><code>-r-xrw---x</code></dd>
<dt><kbd>chmod 562</kbd></dt>
<dd><code>-r-xrw--w-</code></dd>
<dt><kbd>chmod 563</kbd></dt>
<dd><code>-r-xrw--wx</code></dd>
<dt><kbd>chmod 564</kbd></dt>
<dd><code>-r-xrw-r--</code></dd>
<dt><kbd>chmod 565</kbd></dt>
<dd><code>-r-xrw-r-x</code></dd>
<dt><kbd>chmod 566</kbd></dt>
<dd><code>-r-xrw-rw-</code></dd>
<dt><kbd>chmod 567</kbd></dt>
<dd><code>-r-xrw-rwx</code></dd>
<dt><kbd>chmod 570</kbd></dt>
<dd><code>-r-xrwx---</code></dd>
<dt><kbd>chmod 571</kbd></dt>
<dd><code>-r-xrwx--x</code></dd>
<dt><kbd>chmod 572</kbd></dt>
<dd><code>-r-xrwx-w-</code></dd>
<dt><kbd>chmod 573</kbd></dt>
<dd><code>-r-xrwx-wx</code></dd>
<dt><kbd>chmod 574</kbd></dt>
<dd><code>-r-xrwxr--</code></dd>
<dt><kbd>chmod 575</kbd></dt>
<dd><code>-r-xrwxr-x</code></dd>
<dt><kbd>chmod 576</kbd></dt>
<dd><code>-r-xrwxrw-</code></dd>
<dt><kbd>chmod 577</kbd></dt>
<dd><code>-r-xrwxrwx</code></dd>
<dt><kbd>chmod 600</kbd></dt>
<dd><code>-rw-------</code></dd>
<dt><kbd>chmod 601</kbd></dt>
<dd><code>-rw------x</code></dd>
<dt><kbd>chmod 602</kbd></dt>
<dd><code>-rw-----w-</code></dd>
<dt><kbd>chmod 603</kbd></dt>
<dd><code>-rw-----wx</code></dd>
<dt><kbd>chmod 604</kbd></dt>
<dd><code>-rw----r--</code></dd>
<dt><kbd>chmod 605</kbd></dt>
<dd><code>-rw----r-x</code></dd>
<dt><kbd>chmod 606</kbd></dt>
<dd><code>-rw----rw-</code></dd>
<dt><kbd>chmod 607</kbd></dt>
<dd><code>-rw----rwx</code></dd>
<dt><kbd>chmod 610</kbd></dt>
<dd><code>-rw---x---</code></dd>
<dt><kbd>chmod 611</kbd></dt>
<dd><code>-rw---x--x</code></dd>
<dt><kbd>chmod 612</kbd></dt>
<dd><code>-rw---x-w-</code></dd>
<dt><kbd>chmod 613</kbd></dt>
<dd><code>-rw---x-wx</code></dd>
<dt><kbd>chmod 614</kbd></dt>
<dd><code>-rw---xr--</code></dd>
<dt><kbd>chmod 615</kbd></dt>
<dd><code>-rw---xr-x</code></dd>
<dt><kbd>chmod 616</kbd></dt>
<dd><code>-rw---xrw-</code></dd>
<dt><kbd>chmod 617</kbd></dt>
<dd><code>-rw---xrwx</code></dd>
<dt><kbd>chmod 620</kbd></dt>
<dd><code>-rw--w----</code></dd>
<dt><kbd>chmod 621</kbd></dt>
<dd><code>-rw--w---x</code></dd>
<dt><kbd>chmod 622</kbd></dt>
<dd><code>-rw--w--w-</code></dd>
<dt><kbd>chmod 623</kbd></dt>
<dd><code>-rw--w--wx</code></dd>
<dt><kbd>chmod 624</kbd></dt>
<dd><code>-rw--w-r--</code></dd>
<dt><kbd>chmod 625</kbd></dt>
<dd><code>-rw--w-r-x</code></dd>
<dt><kbd>chmod 626</kbd></dt>
<dd><code>-rw--w-rw-</code></dd>
<dt><kbd>chmod 627</kbd></dt>
<dd><code>-rw--w-rwx</code></dd>
<dt><kbd>chmod 630</kbd></dt>
<dd><code>-rw--wx---</code></dd>
<dt><kbd>chmod 631</kbd></dt>
<dd><code>-rw--wx--x</code></dd>
<dt><kbd>chmod 632</kbd></dt>
<dd><code>-rw--wx-w-</code></dd>
<dt><kbd>chmod 633</kbd></dt>
<dd><code>-rw--wx-wx</code></dd>
<dt><kbd>chmod 634</kbd></dt>
<dd><code>-rw--wxr--</code></dd>
<dt><kbd>chmod 635</kbd></dt>
<dd><code>-rw--wxr-x</code></dd>
<dt><kbd>chmod 636</kbd></dt>
<dd><code>-rw--wxrw-</code></dd>
<dt><kbd>chmod 637</kbd></dt>
<dd><code>-rw--wxrwx</code></dd>
<dt><kbd>chmod 640</kbd></dt>
<dd><code>-rw-r-----</code></dd>
<dt><kbd>chmod 641</kbd></dt>
<dd><code>-rw-r----x</code></dd>
<dt><kbd>chmod 642</kbd></dt>
<dd><code>-rw-r---w-</code></dd>
<dt><kbd>chmod 643</kbd></dt>
<dd><code>-rw-r---wx</code></dd>
<dt><kbd>chmod 644</kbd></dt>
<dd><code>-rw-r--r--</code></dd>
<dt><kbd>chmod 645</kbd></dt>
<dd><code>-rw-r--r-x</code></dd>
<dt><kbd>chmod 646</kbd></dt>
<dd><code>-rw-r--rw-</code></dd>
<dt><kbd>chmod 647</kbd></dt>
<dd><code>-rw-r--rwx</code></dd>
<dt><kbd>chmod 650</kbd></dt>
<dd><code>-rw-r-x---</code></dd>
<dt><kbd>chmod 651</kbd></dt>
<dd><code>-rw-r-x--x</code></dd>
<dt><kbd>chmod 652</kbd></dt>
<dd><code>-rw-r-x-w-</code></dd>
<dt><kbd>chmod 653</kbd></dt>
<dd><code>-rw-r-x-wx</code></dd>
<dt><kbd>chmod 654</kbd></dt>
<dd><code>-rw-r-xr--</code></dd>
<dt><kbd>chmod 655</kbd></dt>
<dd><code>-rw-r-xr-x</code></dd>
<dt><kbd>chmod 656</kbd></dt>
<dd><code>-rw-r-xrw-</code></dd>
<dt><kbd>chmod 657</kbd></dt>
<dd><code>-rw-r-xrwx</code></dd>
<dt><kbd>chmod 660</kbd></dt>
<dd><code>-rw-rw----</code></dd>
<dt><kbd>chmod 661</kbd></dt>
<dd><code>-rw-rw---x</code></dd>
<dt><kbd>chmod 662</kbd></dt>
<dd><code>-rw-rw--w-</code></dd>
<dt><kbd>chmod 663</kbd></dt>
<dd><code>-rw-rw--wx</code></dd>
<dt><kbd>chmod 664</kbd></dt>
<dd><code>-rw-rw-r--</code></dd>
<dt><kbd>chmod 665</kbd></dt>
<dd><code>-rw-rw-r-x</code></dd>
<dt><kbd>chmod 666</kbd></dt>
<dd><code>-rw-rw-rw-</code></dd>
<dt><kbd>chmod 667</kbd></dt>
<dd><code>-rw-rw-rwx</code></dd>
<dt><kbd>chmod 670</kbd></dt>
<dd><code>-rw-rwx---</code></dd>
<dt><kbd>chmod 671</kbd></dt>
<dd><code>-rw-rwx--x</code></dd>
<dt><kbd>chmod 672</kbd></dt>
<dd><code>-rw-rwx-w-</code></dd>
<dt><kbd>chmod 673</kbd></dt>
<dd><code>-rw-rwx-wx</code></dd>
<dt><kbd>chmod 674</kbd></dt>
<dd><code>-rw-rwxr--</code></dd>
<dt><kbd>chmod 675</kbd></dt>
<dd><code>-rw-rwxr-x</code></dd>
<dt><kbd>chmod 676</kbd></dt>
<dd><code>-rw-rwxrw-</code></dd>
<dt><kbd>chmod 677</kbd></dt>
<dd><code>-rw-rwxrwx</code></dd>
<dt><kbd>chmod 700</kbd></dt>
<dd><code>-rwx------</code></dd>
<dt><kbd>chmod 701</kbd></dt>
<dd><code>-rwx-----x</code></dd>
<dt><kbd>chmod 702</kbd></dt>
<dd><code>-rwx----w-</code></dd>
<dt><kbd>chmod 703</kbd></dt>
<dd><code>-rwx----wx</code></dd>
<dt><kbd>chmod 704</kbd></dt>
<dd><code>-rwx---r--</code></dd>
<dt><kbd>chmod 705</kbd></dt>
<dd><code>-rwx---r-x</code></dd>
<dt><kbd>chmod 706</kbd></dt>
<dd><code>-rwx---rw-</code></dd>
<dt><kbd>chmod 707</kbd></dt>
<dd><code>-rwx---rwx</code></dd>
<dt><kbd>chmod 710</kbd></dt>
<dd><code>-rwx--x---</code></dd>
<dt><kbd>chmod 711</kbd></dt>
<dd><code>-rwx--x--x</code></dd>
<dt><kbd>chmod 712</kbd></dt>
<dd><code>-rwx--x-w-</code></dd>
<dt><kbd>chmod 713</kbd></dt>
<dd><code>-rwx--x-wx</code></dd>
<dt><kbd>chmod 714</kbd></dt>
<dd><code>-rwx--xr--</code></dd>
<dt><kbd>chmod 715</kbd></dt>
<dd><code>-rwx--xr-x</code></dd>
<dt><kbd>chmod 716</kbd></dt>
<dd><code>-rwx--xrw-</code></dd>
<dt><kbd>chmod 717</kbd></dt>
<dd><code>-rwx--xrwx</code></dd>
<dt><kbd>chmod 720</kbd></dt>
<dd><code>-rwx-w----</code></dd>
<dt><kbd>chmod 721</kbd></dt>
<dd><code>-rwx-w---x</code></dd>
<dt><kbd>chmod 722</kbd></dt>
<dd><code>-rwx-w--w-</code></dd>
<dt><kbd>chmod 723</kbd></dt>
<dd><code>-rwx-w--wx</code></dd>
<dt><kbd>chmod 724</kbd></dt>
<dd><code>-rwx-w-r--</code></dd>
<dt><kbd>chmod 725</kbd></dt>
<dd><code>-rwx-w-r-x</code></dd>
<dt><kbd>chmod 726</kbd></dt>
<dd><code>-rwx-w-rw-</code></dd>
<dt><kbd>chmod 727</kbd></dt>
<dd><code>-rwx-w-rwx</code></dd>
<dt><kbd>chmod 730</kbd></dt>
<dd><code>-rwx-wx---</code></dd>
<dt><kbd>chmod 731</kbd></dt>
<dd><code>-rwx-wx--x</code></dd>
<dt><kbd>chmod 732</kbd></dt>
<dd><code>-rwx-wx-w-</code></dd>
<dt><kbd>chmod 733</kbd></dt>
<dd><code>-rwx-wx-wx</code></dd>
<dt><kbd>chmod 734</kbd></dt>
<dd><code>-rwx-wxr--</code></dd>
<dt><kbd>chmod 735</kbd></dt>
<dd><code>-rwx-wxr-x</code></dd>
<dt><kbd>chmod 736</kbd></dt>
<dd><code>-rwx-wxrw-</code></dd>
<dt><kbd>chmod 737</kbd></dt>
<dd><code>-rwx-wxrwx</code></dd>
<dt><kbd>chmod 740</kbd></dt>
<dd><code>-rwxr-----</code></dd>
<dt><kbd>chmod 741</kbd></dt>
<dd><code>-rwxr----x</code></dd>
<dt><kbd>chmod 742</kbd></dt>
<dd><code>-rwxr---w-</code></dd>
<dt><kbd>chmod 743</kbd></dt>
<dd><code>-rwxr---wx</code></dd>
<dt><kbd>chmod 744</kbd></dt>
<dd><code>-rwxr--r--</code></dd>
<dt><kbd>chmod 745</kbd></dt>
<dd><code>-rwxr--r-x</code></dd>
<dt><kbd>chmod 746</kbd></dt>
<dd><code>-rwxr--rw-</code></dd>
<dt><kbd>chmod 747</kbd></dt>
<dd><code>-rwxr--rwx</code></dd>
<dt><kbd>chmod 750</kbd></dt>
<dd><code>-rwxr-x---</code></dd>
<dt><kbd>chmod 751</kbd></dt>
<dd><code>-rwxr-x--x</code></dd>
<dt><kbd>chmod 752</kbd></dt>
<dd><code>-rwxr-x-w-</code></dd>
<dt><kbd>chmod 753</kbd></dt>
<dd><code>-rwxr-x-wx</code></dd>
<dt><kbd>chmod 754</kbd></dt>
<dd><code>-rwxr-xr--</code></dd>
<dt><kbd>chmod 755</kbd></dt>
<dd><code>-rwxr-xr-x</code></dd>
<dt><kbd>chmod 756</kbd></dt>
<dd><code>-rwxr-xrw-</code></dd>
<dt><kbd>chmod 757</kbd></dt>
<dd><code>-rwxr-xrwx</code></dd>
<dt><kbd>chmod 760</kbd></dt>
<dd><code>-rwxrw----</code></dd>
<dt><kbd>chmod 761</kbd></dt>
<dd><code>-rwxrw---x</code></dd>
<dt><kbd>chmod 762</kbd></dt>
<dd><code>-rwxrw--w-</code></dd>
<dt><kbd>chmod 763</kbd></dt>
<dd><code>-rwxrw--wx</code></dd>
<dt><kbd>chmod 764</kbd></dt>
<dd><code>-rwxrw-r--</code></dd>
<dt><kbd>chmod 765</kbd></dt>
<dd><code>-rwxrw-r-x</code></dd>
<dt><kbd>chmod 766</kbd></dt>
<dd><code>-rwxrw-rw-</code></dd>
<dt><kbd>chmod 767</kbd></dt>
<dd><code>-rwxrw-rwx</code></dd>
<dt><kbd>chmod 770</kbd></dt>
<dd><code>-rwxrwx---</code></dd>
<dt><kbd>chmod 771</kbd></dt>
<dd><code>-rwxrwx--x</code></dd>
<dt><kbd>chmod 772</kbd></dt>
<dd><code>-rwxrwx-w-</code></dd>
<dt><kbd>chmod 773</kbd></dt>
<dd><code>-rwxrwx-wx</code></dd>
<dt><kbd>chmod 774</kbd></dt>
<dd><code>-rwxrwxr--</code></dd>
<dt><kbd>chmod 775</kbd></dt>
<dd><code>-rwxrwxr-x</code></dd>
<dt><kbd>chmod 776</kbd></dt>
<dd><code>-rwxrwxrw-</code></dd>
<dt><kbd>chmod 777</kbd></dt>
<dd><code>-rwxrwxrwx</code></dd>
</dl>
<hr class="C" />




<h2>Congratulations!</h2>
<p>Here's my custom stat function, which I am definately not finished with, so check back in a couple days and if you find any improvements please hook me up with a comment!</p>

<pre>
function askapache_stat( $filename ) {
$p=@fileperms($filename);
$s=@stat($filename);
$str=&#039;&#039;;
$t=decoct($s[&#039;mode&#039;] &amp; 0170000);
&nbsp;
switch (octdec($t)) {
case 0140000: $str = &#039;s&#039;; $stat[&#039;type&#039;]=&#039;socket&#039;; break;
case 0120000: $str = &#039;l&#039;; $stat[&#039;type&#039;]=&#039;link&#039;; break;
case 0100000: $str = &#039;-&#039;; $stat[&#039;type&#039;]=&#039;file&#039;; break;
case 0060000: $str = &#039;b&#039;; $stat[&#039;type&#039;]=&#039;block&#039;; break;
case 0040000: $str = &#039;d&#039;; $stat[&#039;type&#039;]=&#039;dir&#039;; break;
case 0020000: $str = &#039;c&#039;; $stat[&#039;type&#039;]=&#039;char&#039;; break;
case 0010000: $str = &#039;p&#039;; $stat[&#039;type&#039;]=&#039;fifo&#039;; break;
default: $str = &#039;u&#039;; $stat[&#039;type&#039;]=&#039;unknown&#039;; break;
}
&nbsp;
$stat[&#039;type_octal&#039;] = sprintf("%07o", octdec($t));
&nbsp;
$str .= (($p&amp;0x0100)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0080)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0040)?(($p&amp;0x0800)?&#039;s&#039;:&#039;x&#039;):(($p&amp;0x0800)?&#039;S&#039;:&#039;-&#039;));
$str .= (($p&amp;0x0020)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0010)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0008)?(($p&amp;0x0400)?&#039;s&#039;:&#039;x&#039;):(($p&amp;0x0400)?&#039;S&#039;:&#039;-&#039;));
$str .= (($p&amp;0x0004)?&#039;r&#039;:&#039;-&#039;).(($p&amp;0x0002)?&#039;w&#039;:&#039;-&#039;).(($p&amp;0x0001)?(($p&amp;0x0200)?&#039;t&#039;:&#039;x&#039;):(($p&amp;0x0200)?&#039;T&#039;:&#039;-&#039;));
&nbsp;
$stat[&#039;default_umask&#039;]=sprintf("%04o",umask());
$stat[&#039;perm_human&#039;]=$str;
$stat[&#039;perm_octal1&#039;] = sprintf( "%o", ( $s[&#039;mode&#039;] &amp; 00777 ) );
$stat[&#039;perm_octal2&#039;] = sprintf("0%o", 0777 &amp; $p);
$stat[&#039;perm_dec&#039;] = sprintf("%04o", $p);
$stat[&#039;perm_mode&#039;]=$s[&#039;mode&#039;];   // File mode.
&nbsp;
$stat[&#039;file&#039;] = @realpath($filename);
$stat[&#039;basename&#039;] = basename( $filename );
&nbsp;
$stat[&#039;user_id&#039;] = $s[&#039;uid&#039;];
$stat[&#039;group_id&#039;] = $s[&#039;gid&#039;];
&nbsp;
$stat[&#039;device&#039;]=$s[&#039;dev&#039;];      // Device
$stat[&#039;device_number&#039;]=$s[&#039;rdev&#039;];    // Device number, if device.
$stat[&#039;inode&#039;]=$s[&#039;ino&#039;];      // File serial number
$stat[&#039;link_count&#039;]=$s[&#039;nlink&#039;];    // link count
if($stat[&#039;type&#039;]==&#039;link&#039;)$stat[&#039;link_to&#039;]=@readlink( $filename );
&nbsp;
$stat[&#039;size&#039;]=$s[&#039;size&#039;];    // Size of file, in bytes.
$stat[&#039;block_size&#039;]=$s[&#039;blksize&#039;];  // Optimal block size for I/O.
$stat[&#039;blocks&#039;]=$s[&#039;blocks&#039;];  // Number 512-byte blocks allocated
&nbsp;
$stat[&#039;time_access&#039;]=@date( &#039;Y M D H:i:s&#039;,$s[&#039;atime&#039;]);    // Time of last access.
$stat[&#039;time_modified&#039;]=@date( &#039;Y M D H:i:s&#039;,$s[&#039;mtime&#039;]);    // Time of last modification
$stat[&#039;time_created&#039;]=@date( &#039;Y M D H:i:s&#039;,$s[&#039;ctime&#039;]);    // Time of last status change
&nbsp;
clearstatcache();
return $stat;
}
&nbsp;
header(&#039;Content-Type: text/plain&#039;);
$stat=askapache_stat(__FILE__);
print_r($stat);
</pre>






<h3>Defining Permission Bits</h3>
<pre>
!defined(&#039;S_IFMT&#039;) &amp;&amp; define(&#039;S_IFMT&#039;, 0170000); //  mask for all types
!defined(&#039;S_IFSOCK&#039;) &amp;&amp; define(&#039;S_IFSOCK&#039;, 0140000); // type: socket
!defined(&#039;S_IFLNK&#039;) &amp;&amp; define(&#039;S_IFLNK&#039;, 0120000); // type:  symbolic link
!defined(&#039;S_IFREG&#039;) &amp;&amp; define(&#039;S_IFREG&#039;, 0100000); // type:  regular file
!defined(&#039;S_IFBLK&#039;) &amp;&amp; define(&#039;S_IFBLK&#039;, 0060000); // type:  block device
!defined(&#039;S_IFDIR&#039;) &amp;&amp; define(&#039;S_IFDIR&#039;, 0040000); // type:  directory
!defined(&#039;S_IFCHR&#039;) &amp;&amp; define(&#039;S_IFCHR&#039;, 0020000); // type:  character device
!defined(&#039;S_IFIFO&#039;) &amp;&amp; define(&#039;S_IFIFO&#039;, 0010000); // type:  fifo
&nbsp;
!defined(&#039;S_ISUID&#039;) &amp;&amp; define(&#039;S_ISUID&#039;, 0004000); // set-uid bit
!defined(&#039;S_ISGID&#039;) &amp;&amp; define(&#039;S_ISGID&#039;, 0002000); // set-gid bit
!defined(&#039;S_ISVTX&#039;) &amp;&amp; define(&#039;S_ISVTX&#039;, 0001000); // sticky bit
!defined(&#039;S_IRWXU&#039;) &amp;&amp; define(&#039;S_IRWXU&#039;, 00700); //  mask for owner permissions
!defined(&#039;S_IRUSR&#039;) &amp;&amp; define(&#039;S_IRUSR&#039;, 00400); //  owner: read permission
!defined(&#039;S_IWUSR&#039;) &amp;&amp; define(&#039;S_IWUSR&#039;, 00200); //  owner: write permission
!defined(&#039;S_IXUSR&#039;) &amp;&amp; define(&#039;S_IXUSR&#039;, 00100); //  owner: execute permission
!defined(&#039;S_IRWXG&#039;) &amp;&amp; define(&#039;S_IRWXG&#039;, 00070); //  mask for group permissions
!defined(&#039;S_IRGRP&#039;) &amp;&amp; define(&#039;S_IRGRP&#039;, 00040); //  group: read permission
!defined(&#039;S_IWGRP&#039;) &amp;&amp; define(&#039;S_IWGRP&#039;, 00020); //  group: write permission
!defined(&#039;S_IXGRP&#039;) &amp;&amp; define(&#039;S_IXGRP&#039;, 00010); //  group: execute permission
!defined(&#039;S_IRWXO&#039;) &amp;&amp; define(&#039;S_IRWXO&#039;, 00007); //  mask for others permissions
!defined(&#039;S_IROTH&#039;) &amp;&amp; define(&#039;S_IROTH&#039;, 00004); //  others:  read permission
!defined(&#039;S_IWOTH&#039;) &amp;&amp; define(&#039;S_IWOTH&#039;, 00002); //  others:  write permission
!defined(&#039;S_IXOTH&#039;) &amp;&amp; define(&#039;S_IXOTH&#039;, 00001); //  others:  execute permission
&nbsp;
!defined(&#039;S_IRWXUGO&#039;) &amp;&amp; define(&#039;S_IRWXUGO&#039;, (S_IRWXU | S_IRWXG | S_IRWXO));
!defined(&#039;S_IALLUGO&#039;) &amp;&amp; define(&#039;S_IALLUGO&#039;, (S_ISUID | S_ISGID | S_ISVTX | S_IRWXUGO));
!defined(&#039;S_IRUGO&#039;) &amp;&amp; define(&#039;S_IRUGO&#039;, (S_IRUSR | S_IRGRP | S_IROTH));
!defined(&#039;S_IWUGO&#039;) &amp;&amp; define(&#039;S_IWUGO&#039;, (S_IWUSR | S_IWGRP | S_IWOTH));
!defined(&#039;S_IXUGO&#039;) &amp;&amp; define(&#039;S_IXUGO&#039;, (S_IXUSR | S_IXGRP | S_IXOTH));
!defined(&#039;S_IRWUGO&#039;) &amp;&amp; define(&#039;S_IRWUGO&#039;, (S_IRUGO | S_IWUGO));
</pre>




<h2>How File Permissions Work</h2>
<p>When PHP is installed on your server by you or whoever runs the server, it uses the file permissions that are used by the Operating System running the server..  If you are smart or just lucky than you are running some type of BSD/Unix/Solaris/Linux/Sun based Operating system and PHP won't have any problems.  If you are running on a Locked, proprietary OS like Windows, PHP will still work but it has to use a lot of shortcuts and hacks to basically "Pretend" to act like the OS is BSD/Unix, and some key features just won't be available.</p>

<h2>The OS Permission Bits</h2>
<p>Here's the file permissions my Linux server uses, and which PHP automatically uses.  The code basically just defines the default permissions for files, and defines the file atributes for each file that you can access by using the stat function, which I've improved upon to make things easier.</p>
<p>Download: <a href='http://uploads.askapache.com/2008/11/stat.h' title="POSIX Standard: 5.6 File Characteristics">POSIX Standard: 5.6 File Characteristics<code>sys/stat.h</code></a></p>
<h3>Protection bits for File Owner</h3>
<pre>
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
</pre>

<h3>Protection bits for File Group</h3>
<pre>
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
</pre>

<h3>Protection bits for All Others</h3>
<pre>
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
</pre>


<h2>Some Example Permissions</h2>
<p><code>0477</code>  // owner has read only, other and group has rwx
<code>0677</code>  // owner has rw only, other and group has rwx</p>

<p><code>0444</code>  // all have read only
<code>0666</code>  // all have rw only</p>

<p><code>0400</code>  // owner has read only, group and others have no permission
<code>0600</code> // owner has rw only, group and others have no permission</p>

<p><code>0470</code>  // owner has read only, group has rwx, others have no permission
<code>0407</code>  // owner has read only, other has rwx, group has no permission</p>

<p><code>0670</code>  // owner has rw only, group has rwx, others have no permission
<code>0607</code>  // owner has rw only, group has no permission and others have rwx</p>


<h2>What's a File</h2>
<p>A file is not merely its contents, a name, and a file type. A file also has an owner (a user ID), a group (a group ID), permissions (what the owner can do with the file, what people in the group can do, and what everyone else can do), various timestamps, and other information. Collectively, we call these a file's attributes.</p>

<h2>Structure of File Mode Bits</h2>
<p>The file mode bits have two parts: the file permission bits, which control ordinary access to the file, and special mode bits, which affect only some files.</p>
<p>There are three kinds of permissions that a user can have for a file:</p>
<ol>
<li>permission to read the file. For directories, this means permission to list the contents of the directory.</li>
<li>permission to write to (change) the file. For directories, this means permission to create and remove files in the directory.</li>
<li>permission to execute the file (run it as a program). For directories, this means permission to access files in the directory.</li>
</ol>

<p>There are three categories of users who may have different permissions to perform any of the above operations on a file:</p>
<ol>
<li>the file's owner.</li>
<li>other users who are in the file's group</li>
<li>everyone else.</li>
</ol>

<p>Files are given an owner and group when they are created. Usually the owner is the current user and the group is the group of the directory the file is in, but this varies with the operating system, the file system the file is created on, and the way the file is created. You can change the owner and group of a file by using the <strong>chown</strong> and <strong>chgrp</strong> commands.</p>
<p>In addition to the three sets of three permissions listed above, the file mode bits have three special components, which affect only executable files (programs) and, on most systems, directories:</p>
<ol>
<li>Set the process's effective user ID to that of the file upon execution (called the set-user-ID bit, or sometimes the setuid bit). For directories on a few systems, give files created in the directory the same owner as the directory, no matter who creates them, and set the set-user-ID bit of newly-created subdirectories.</li>
<li>Set the process's effective group ID to that of the file upon execution (called the set-group-ID bit, or sometimes the setgid bit). For directories on most systems, give files created in the directory the same group as the directory, no matter what group the user who creates them is in, and set the set-group-ID bit of newly-created subdirectories.</li>
<li>Prevent unprivileged users from removing or renaming a file in a directory unless they own the file or the directory; this is called the restricted deletion flag for the directory, and is commonly found on world-writable directories like /tmp.</li>
</ol>

<p>For regular files on some older systems, save the program's text image on the swap device so it will load more quickly when run; this is called the <code>sticky bit</code>.</p>



<h2>Setting Permissions</h2>
<p>The basic symbolic operations on a file's permissions are adding, removing, and setting the permission that certain users have to read, write, and execute or search the file. These operations have the following format:</p>
<p><code>users operation permissions</code></p>

<p>The spaces between the three parts above are shown for readability only; symbolic modes cannot contain spaces.  The users part tells which users' access to the file is changed. It consists of one or more of the following letters (or it can be empty). When more than one of these letters is given, the order that they are in does not matter.</p>
<ul>
<li><strong>u</strong> - the user who owns the file.</li>
<li><strong>g</strong> - other users who are in the file's group.</li>
<li><strong>o</strong> - all other users.</li>
<li><strong>a</strong> - all users; the same as ugo.</li>
</ul>

<p>The operation part tells how to change the affected users' access to the file, and is one of the following symbols:</p>
<ul>
<li><strong>+</strong> - to add the permissions to whatever permissions the users already have for the file.</li>
<li><strong>-</strong> - to remove the permissions from whatever permissions the users already have for the file.</li>
<li><strong>=</strong> - to make the permissions the only permissions that the users have for the file.</li>
</ul>

<p>The permissions part tells what kind of access to the file should be changed; it is normally zero or more of the following letters. As with the users part, the order does not matter when more than one letter is given. Omitting the permissions part is useful only with the = operation, where it gives the specified users no access at all to the file.</p>

<ul>
<li><strong>r</strong> - the permission the users have to read the file.</li>
<li><strong>w</strong> - the permission the users have to write to the file.</li>
<li><strong>x</strong> - the permission the users have to execute the file, or search it if it is a directory.</li>
</ul>

<p>For example, to give everyone permission to read and write a regular file, but not to execute it, use:</p>
<pre>
a=rw
</pre>

<p>To remove write permission for all users other than the file's owner, use:</p>
<pre>
go-w
</pre>

<p>The above command does not affect the access that the owner of the file has to it, nor does it affect whether other users can read or execute the file.</p>

<p>To give everyone except a file's owner no permission to do anything with that file, use the mode below. Other users could still remove the file, if they have write permission on the directory it is in.</p>
<pre>
go=
</pre>

<p>Another way to specify the same thing is:</p>
<pre>
og-rwx
</pre>



<h2>Copying Existing Permissions</h2>
<p>You can base a file's permissions on its existing permissions. To do this, instead of using a series of <strong>r, w, or x</strong> letters after the operator, you use the letter <strong>u, g, or o</strong>. For example, the mode</p>
<pre>
o+g
</pre>

<p>adds the permissions for users who are in a file's group to the permissions that other users have for the file. Thus, if the file started out as mode 664 (rw-rw-r--), the above mode would change it to mode 666 (rw-rw-rw-). If the file had started out as mode 741 (rwxr----x), the above mode would change it to mode 745 (rwxr--r-x). The - and = operations work analogously.</p>






<h2>Umask and Protection</h2>
<p>If the users part of a symbolic mode is omitted, it defaults to a (affect all users), except that any permissions that are set in the system variable umask are not affected. The value of umask can be set using the umask command. Its default value varies from system to system.</p>

<p>Omitting the users part of a symbolic mode is generally not useful with operations other than +. It is useful with + because it allows you to use umask as an easily customizable protection against giving away more permission to files than you intended to.  As an example, if umask has the value 2, which removes write permission for users who are not in the file's group, then the mode:</p>
<pre>
+w
</pre>

<p>adds permission to write to the file to its owner and to other users who are in the file's group, but not to other users. In contrast, the mode:</p>
<pre>
a+w
</pre>

<p>ignores umask, and does give write permission for the file to all users.</p>




<h2>Directories, Set-User-ID and Set-Group-ID Bits</h2>
<p>On most systems, if a directory's set-group-ID bit is set, newly created subfiles inherit the same group as the directory, and newly created subdirectories inherit the set-group-ID bit of the parent directory. On a few systems, a directory's set-user-ID bit has a similar effect on the ownership of new subfiles and the set-user-ID bits of new subdirectories. These mechanisms let users share files more easily, by lessening the need to use chmod or chown to share new files.</p>

<p>These convenience mechanisms rely on the set-user-ID and set-group-ID bits of directories. If commands like chmod and mkdir routinely cleared these bits on directories, the mechanisms would be less convenient and it would be harder to share files. Therefore, a command like chmod does not affect the set-user-ID or set-group-ID bits of a directory unless the user specifically mentions them in a symbolic mode, or sets them in a numeric mode. For example, on systems that support set-group-ID inheritance:</p>

<pre>
# These commands leave the set-user-ID and
# set-group-ID bits of the subdirectories alone,
# so that they retain their default values.
mkdir A B C
chmod 755 A
chmod 0755 B
chmod u=rwx,go=rx C
mkdir -m 755 D
mkdir -m 0755 E
mkdir -m u=rwx,go=rx F
</pre>

<p>If you want to try to set these bits, you must mention them explicitly in the symbolic or numeric modes, e.g.:</p>
<pre>
# These commands try to set the set-user-ID
# and set-group-ID bits of the subdirectories.
mkdir G H
chmod 6755 G
chmod u=rwx,go=rx,a+s H
mkdir -m 6755 I
mkdir -m u=rwx,go=rx,a+s J
</pre>

<p>If you want to try to clear these bits, you must mention them explicitly in a symbolic mode, e.g.:</p>
<pre>
# This command tries to clear the set-user-ID
# and set-group-ID bits of the directory D.
chmod a-s D
</pre>











<h2>Numeric Modes</h2>
<p>The permissions granted to the user, to other users in the file's group, and to other users not in the file's group each require three bits, which are represented as one octal digit. The three special mode bits also require one bit each, and they are as a group represented as another octal digit. Here is how the bits are arranged, starting with the lowest valued bit:</p>

<h3>Other users not in the file's group:</h3>
<pre>
1 Execute/search
2 Write
4 Read
</pre>

<h3>Other users in the file's group:</h3>
<pre>
10 Execute/search
20 Write
40 Read
</pre>

<h3>The file's owner:</h3>
<pre>
100 Execute/search
200 Write
400 Read
</pre>

<h3>Special mode bits:</h3>
<pre>
1000 Restricted deletion flag or sticky bit
2000 Set group ID on execution
4000 Set user ID on execution
</pre>

<p>For example, numeric <code>mode 4755</code> corresponds to symbolic mode <code>u=rwxs,go=rx</code>, and numeric m<code>ode 664</code> corresponds to symbolic mode <code>ug=rw,o=r</code>. Numeric <code>mode 0</code> corresponds to symbolic mode <code>a=</code>.</p>




<h2>Apache's Internal Bits (hex)</h2>
<pre>
#define APR_FPROT_USETID   0x8000 /* Set user id */
#define APR_FPROT_UREAD   0x0400 /* Read by user */
#define APR_FPROT_UWRITE   0x0200 /* Write by user */
#define APR_FPROT_UEXECUTE 0x0100 /* Execute by user */
&nbsp;
#define APR_FPROT_GSETID   0x4000 /* Set group id */
#define APR_FPROT_GREAD   0x0040 /* Read by group */
#define APR_FPROT_GWRITE   0x0020 /* Write by group */
#define APR_FPROT_GEXECUTE 0x0010 /* Execute by group */
&nbsp;
#define APR_FPROT_WSTICKY 0x2000 /* Sticky bit */
#define APR_FPROT_WREAD   0x0004 /* Read by others */
#define APR_FPROT_WWRITE 0x0002 /* Write by others */
#define APR_FPROT_WEXECUTE 0x0001 /* Execute by others */
&nbsp;
#define APR_FPROT_OS_DEFAULT  0x0FFF /* use OS&#039;s default permissions */
&nbsp;
/* additional permission flags for apr_file_copy  and apr_file_append */
#define APR_FPROT_FILE_SOURCE_PERMS 0x1000 /* Copy source file&#039;s permissions */
</pre>


<p>Download: <a href='http://uploads.askapache.com/2008/11/fileacc.c' title="A file to put ALL of the accessor functions for apr_file_t types"><code>httpd-2.2.10/srclib/apr/file_io/unix/fileacc.c</code></a> Here's some interesting bitmasking done by Apache that uses the defined bits set earlier by stat.h</p>
<pre>
apr_unix_perms2mode(perms){
 mode=0;
 if (perms &amp; APR_USETID) mode |= S_ISUID;
 if (perms &amp; APR_UREAD)  mode |= S_IRUSR;
 if (perms &amp; APR_UWRITE) mode |= S_IWUSR;
 if (perms &amp; APR_UEXECUTE) mode |= S_IXUSR;
&nbsp;
 if (perms &amp; APR_GSETID) mode |= S_ISGID;
 if (perms &amp; APR_GREAD)  mode |= S_IRGRP;
 if (perms &amp; APR_GWRITE) mode |= S_IWGRP;
 if (perms &amp; APR_GEXECUTE) mode |= S_IXGRP;
&nbsp;
 if (perms &amp; APR_WSTICKY) mode |= S_ISVTX;
 if (perms &amp; APR_WREAD)  mode |= S_IROTH;
 if (perms &amp; APR_WWRITE) mode |= S_IWOTH;
 if (perms &amp; APR_WEXECUTE) mode |= S_IXOTH;
 return mode;
}
&nbsp;
apr_unix_mode2perms(mode){
 perms = 0;
 if (mode &amp; S_ISUID)perms |= APR_USETID;
 if (mode &amp; S_IRUSR)perms |= APR_UREAD;
 if (mode &amp; S_IWUSR)perms |= APR_UWRITE;
 if (mode &amp; S_IXUSR)perms |= APR_UEXECUTE;
&nbsp;
 if (mode &amp; S_ISGID)perms |= APR_GSETID;
 if (mode &amp; S_IRGRP)perms |= APR_GREAD;
 if (mode &amp; S_IWGRP)perms |= APR_GWRITE;
 if (mode &amp; S_IXGRP)perms |= APR_GEXECUTE;
&nbsp;
 if (mode &amp; S_ISVTX)perms |= APR_WSTICKY;
 if (mode &amp; S_IROTH)perms |= APR_WREAD;
 if (mode &amp; S_IWOTH)perms |= APR_WWRITE;
 if (mode &amp; S_IXOTH)perms |= APR_WEXECUTE;
 return perms;
}
</pre>





<h2>umask</h2>
<pre>
umask(int mask){
 arg1;
 int oldumask;
 int arg_count = ZEND_NUM_ARGS();
 oldumask = umask(077);
&nbsp;
 if (BG(umask) == -1) BG(umask) = oldumask;
 if (arg_count == 0) umask(oldumask);
&nbsp;
 convert_to_long_ex(arg1);
 umask(Z_LVAL_PP(arg1));
 RETURN_LONG(oldumask);
}
</pre>

















<h2>File Attributes</h2>
<p>Each file will have attributes based on the type of OS.. Using the stat command you can view them.</p>

<h3>Viewing stat results</h3>
<pre>
* %a - Access rights in octal
* %A - Access rights in human readable form
* %b - Number of blocks allocated (see %B)
* %B - The size in bytes of each block reported by %b
* %d - Device number in decimal
* %D - Device number in hex
* %f - Raw mode in hex
* %F - File type
* %g - Group ID of owner
* %G - Group name of owner
* %h - Number of hard links
* %i - Inode number
* %n - File name
* %N - Quoted file name with dereference if symbolic link
* %o - I/O block size
* %s - Total size, in bytes
* %t - Major device type in hex
* %T - Minor device type in hex
* %u - User ID of owner
* %U - User name of owner
* %x - Time of last access
* %X - Time of last access as seconds since Epoch
* %y - Time of last modification
* %Y - Time of last modification as seconds since Epoch
* %z - Time of last change
* %Z - Time of last change as seconds since Epoch
</pre>




<h2>The OS Attribute Bits</h2>
<p>These defined values are what allows your operating system to determine the type of file being accessed. </p>
<pre>
#define S_IFMT   00170000  /* These bits determine file type. */
#define S_IFSOCK 0140000  /* Socket file */
#define S_IFLNK   0120000  /* Symbolic Link */
#define S_IFREG   0100000  /* Regular file */
#define S_IFDIR   0040000  /* Directory */
#define S_IFIFO  0010000   /* FIFO first-in-first-out file */
&nbsp;
/* Such devices can be read either a character at a time or a "block" (many characters) at a time,
hence we say there are block special files and character special files. */
#define S_IFBLK   0060000  /* Block device */
#define S_IFCHR  0020000  /* Character device */
</pre>

<h3>Special Permission Bits</h3>
<pre>
#define S_ISUID  0004000  /* Set user ID on execution.  */
#define S_ISGID  0002000  /* Set group ID on execution.  */
#define S_ISVTX  0001000 /* Save swapped text after use (sticky).  */
</pre>

<h3>Bitmasking to determine Filetype</h3>
<pre>
#define S_ISLNK(m) (((m) &amp; S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) &amp; S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) &amp; S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) &amp; S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) &amp; S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) &amp; S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) &amp; S_IFMT) == S_IFSOCK)
</pre>

<h3>Default Permission Masks</h3>
<pre>
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO  (S_IRUSR|S_IRGRP|S_IROTH)
#define S_IWUGO  (S_IWUSR|S_IWGRP|S_IWOTH)
#define S_IXUGO  (S_IXUSR|S_IXGRP|S_IXOTH)
</pre>


<p>Download: <a href='http://uploads.askapache.com/2008/11/filestat.c' title="handles file stat"><code>httpd-2.2.10/srclib/apr/file_io/unix/filestat.c</code></a>, this file shows a simple way to determine the type of file.</p>
<pre>
filetype_from_mode(mode){
 type;
 switch (mode &amp; S_IFMT) {
  case S_IFREG:  type = APR_REG;  break;
  case S_IFDIR:  type = APR_DIR;  break;
  case S_IFLNK:  type = APR_LNK;  break;
&nbsp;
  case S_IFCHR:  type = APR_CHR;  break;
  case S_IFBLK:  type = APR_BLK;  break;
  case S_IFFIFO: type = APR_PIPE; break;
  case S_IFSOCK: type = APR_SOCK; break;
  default: type = APR_UNKFILE;
 }
 return type;
}
</pre>

<h3>Apache Stat Bits</h3>
<pre>
#define APR_FINFO_LINK  0x00000001 /* Stat the link not the file itself if it is a link */
#define APR_FINFO_MTIME  0x00000010 /* Modification Time */
#define APR_FINFO_CTIME  0x00000020 /* Creation or inode-changed time */
#define APR_FINFO_ATIME  0x00000040 /* Access Time */
#define APR_FINFO_SIZE  0x00000100 /* Size of the file */
#define APR_FINFO_CSIZE  0x00000200 /* Storage size consumed by the file */
#define APR_FINFO_DEV  0x00001000 /* Device */
#define APR_FINFO_INODE  0x00002000 /* Inode */
#define APR_FINFO_NLINK  0x00004000 /* Number of links */
#define APR_FINFO_TYPE  0x00008000 /* Type */
#define APR_FINFO_USER  0x00010000 /* User */
#define APR_FINFO_GROUP  0x00020000 /* Group */
#define APR_FINFO_UPROT  0x00100000 /* User protection bits */
#define APR_FINFO_GPROT  0x00200000 /* Group protection bits */
#define APR_FINFO_WPROT  0x00400000 /* World protection bits */
#define APR_FINFO_ICASE  0x01000000 /* if dev is case insensitive */
#define APR_FINFO_NAME  0x02000000 /* name in proper case */
#define APR_FINFO_MIN  0x00008170 /* type, mtime, ctime, atime, size */
#define APR_FINFO_IDENT  0x00003000 /* dev and inode */
#define APR_FINFO_OWNER  0x00030000 /* user and group */
#define APR_FINFO_PROT  0x00700000 /* all protections */
#define APR_FINFO_NORM  0x0073b170 /* an atomic unix apr_stat() */
#define APR_FINFO_DIRENT 0x02000000 /* an atomic unix apr_dir_read() */
</pre>

<h3>The Apache file information structure.</h3>
<pre>
apr_uid_t user;  /* The user id that owns the file */
apr_gid_t group;  /* The group id that owns the file */
apr_ino_t inode; /* The inode of the file. */
apr_dev_t device; /* The id of the device the file is on. */
apr_int32_t nlink; /* The number of hard links to the file. */
apr_off_t size;  /* The size of the file */
apr_off_t csize; /* The storage size consumed by the file */
apr_time_t atime; /* The time the file was last accessed */
apr_time_t mtime; /* The time the file was last modified */
apr_time_t ctime; /* The time the file was created, or the inode was last changed */
const char *fname; /* The pathname of the file (possibly unrooted) */
const char *name; /* The file&#039;s name (no path) in filesystem case */
</pre>



<h3>File Time Attributes</h3>
<blockquote><cite><a href="http://php.net/manual/en/function.touch.php">touch</a></cite>
<p>If changing both the access and modification times to the current time, touch can change the timestamps for files that the user running it does not own but has write permission for. Otherwise, the user must own the files.</p>
</blockquote>

<p>Although touch provides options for changing two of the times the times of last access and modification of a file, there is actually a third one as well: the inode change time. This is often referred to as a file's ctime. The inode change time represents the time when the file's meta-information last changed. One common example of this is when the permissions of a file change. Changing the permissions doesn't access the file, so the atime doesn't change, nor does it modify the file, so the mtime doesn't change. Yet, something about the file itself has changed, and this must be noted somewhere. This is the job of the ctime field. This is necessary, so that, for example, a backup program can make a fresh copy of the file, including the new permissions value. Another operation that modifies a file's ctime without affecting the others is renaming. In any case, it is not possible, in normal operations, for a user to change the ctime field to a user-specified value.</p>
</blockquote>













<a name="Shared_hosting_user_security"></a>
<h2>Shared hosting user security </h2>
<ul>
	<li><a href="#Shared_hosting_user_security">Shared hosting user security</a></li>
	<li><a href="#Apache_Security">Apache Security</a></li>
	<li><a href="#Multiuser_security_setup_example">Multiuser security setup example</a></li>
	<li><a href="#SSH_key_fingerprints">SSH key fingerprints</a></li>
	<li><a href="#External_Links">External Links</a></li>
</ul>
<p>WebHost allows you to create multiple users per account. Each user can have domain assigned to its home home directory accessible via FTP or SSH/SCP. The problem with multiple users on the same account is that they share the same default unix group, and default permissions allow their files to be easily modified by the members of this group. Usually this doesn't pose a problem as each user is probably trusted by account owner to not to mess with others files, but if one of the users have their web application hacked then all other users on the same account will be in danger. </p>
<p>By default all files in your account are created with 644 privileges and directories are with 775. That means any user can read your files and any user from the same account can move and add files in your freshly made directories. Your home directory is different, though. By default it carries 751 attribute meaning that only members of your group can see your files, but can't add any new. These group access schemes are possible, because every user in your account has its primary/default group set to "pgxxxxxx", which is assigned to every new file you create by default. The normal way to secure users from web-intrusion is to assign a separate group to the web-server user, removing it from default group. This way, exploited scripts will not be able to traverse into home directories of other users on your account. To allow account users to update centralized web-site they could be added to web-site group explicitly. But this "normal way" doesn't work with DreamHost, because you can't delete web-user from the default group and unless you set access for every new file explicitly, it will be possible for an intruder to read it. </p>
<p>To make managing privileges easier in interactive sessions "umask 007" command can be specified in your .bash_profile - this makes all new files carry xx0 mask. You also need to control your scripts (web based or cron/shell) so that they set mask for critical files explicitly. To secure account users from access by means of hacked user script you would also like to define another group for every user in your account and change group ownership of the user's home directory to that group with "set gid" bit set (and optional umask 007 in .bash_profile). </p>
<p>Therefore, to secure your users from web-intrusion you need to: </p>
<ol>
	<li>Add a separate user and group for every domain where apache will be running </li>
	<li>Add a separate group for other user accounts </li>
	<li>Change the default group for new files created by your users by changing the group of their home directory and setting "set gid" bit for it (it is impossible to do this with FTP accounts, therefore you will need to login in each account via SSH) </li>
	<li>Add users who need access to web-site into the web-user group </li>
	<li>Optionally set umask 007 in .bash_profile for every user to tweak default WebHost775/664 permissions to something like 770/660 for directories and files that are not meant to be read by Apache (660 could also be used for all web scripts including .php as they are not read by dhapache CGI, but merely executed) </li>
</ol>
<h2><a name="Apache_Security"></a>Apache Security </h2>
<p>All your web files that need to be read by Apache should be readable by everyone as Apache itself is run under dhapache user. However, executable scripts like .php are executed under your own user and do not have to be world readable as they are not actually read by Apache, but executed via <a href="http://en.wikipedia.org/wiki/suEXEC">suEXEC</a>. Quite the opposite - to prevent your code or database settings from being messed by any third-parties you SHOULD set permissions to these files explicitly to something like 640 or even 600 depending on who do you trust. </p>
<a name="Multiuser_security_setup_example"></a>
<h2>Multiuser security setup example </h2>
<p>For our example, we will create a <em>rainforce_www</em> user and a <em>aapp_www</em> group for serving web files with apache and setup a <em>rainforce</em> user with a 'aapp<em> group to manage mail and keep other files on DH privately. Since these records already exist, you will need to subsitute your own names.</em> </p>
<ul>
	<li>Login to create the users <em>rainforce_www</em> and <em>rainforce</em> with shell access. </li>
	<li>Create two groups - <em>aapp_www</em> and <em>aapp</em>. Note that users created in previous step are still members of the same default <em>pg</em>xxxxxx group. </li>
	<li>Add <em>rainforce_www</em> to 'the 'aapp_www<em> group and </em>rainforce<em> to both the </em>aapp_www<em> and </em>aapp<em> groups</em> </li>
	<li>Move your domain to <em>rainforce_www</em> account (mine is rainforce.org) </li>
	<li>Now login to SSH with your <em>rainforce_www</em> user and change the default group for your home directory with "sgid" bit set to make all current and new files/directories created in this directory have the same <em>aapp_www</em> group. </li>
</ul>
<pre>
 $ chgrp -R aapp_www .
 $ chmod 2751 .
 $ chmod 2771 rainforce.org
</pre>
<p>By setting 2771 the directory will be writable by the owner, the group and will be only executable by others. The contents of an executable only directory cannot be listed, but the files inside it can be read (if the permissions of the file allow it). It is important that the directory can be executable in order to allow static content (e.g. .html files) inside it to be read. Remember that directories you don't want anyone to have web access to, should be 0770 (writable by the owner and group, or 0750 writable by the owner and readable by group). Such strict permissions should by applied to password files, php include files or databases files (such as SQLite, BDB, etc). </p>
<ul>
	<li>Do the same for <em>rainforce</em> user, but specify <em>aapp</em> group instead. </li>
</ul>
<pre>
 $ chgrp -R aapp .
 $ chmod 2751 .
</pre>
<ul>
	<li>Optionally modify umask in .bash_profile in user's home to 007 to make all files created by this user have 660 permissions set by default. If you want that newly created files by accessible by the web, you need to manually setup it's permissions to 664. </li>
</ul>
<p>Now I can login as the user "rainforce" and update the web-site in the ../rainforce_www/rainforce.org directory. There is one more setup needed. Because files copied from other accounts can have 644 permissions set instead of 664, you need a script which will update permissions to 664 or 660 to allow other group members modify such files. </p>
<h2><a name="SSH_key_fingerprints"></a>SSH key fingerprints </h2>
<p>Just gen your own I guess </p>
<h2>External Links </h2>
<ul>
	<li><a href="http://oldfield.wattle.id.au/luv/permissions.html" title="http://oldfield.wattle.id.au/luv/permissions.html" rel="nofollow">Introduction to Unix file permissions</a> </li>
	<li><a href="http://www.perlfect.com/articles/chmod.shtml" title="http://www.perlfect.com/articles/chmod.shtml" rel="nofollow">Understanding UNIX permission and chmod</a> </li>
</ul>
<p>Original Article from <a href="http://wiki.dreamhost.com/index.php?title=Security">DreamHost Wiki</a></p>
<p>Content is available under <a href="http://www.gnu.org/copyleft/fdl.html" class="external " title="http://www.gnu.org/copyleft/fdl.html" rel="nofollow">GNU Free Documentation License 1.2</a>.</p>





<h2>Example File Permission Bits</h2>

<h3><code>/usr/lib/w3m/cgi-bin/dirlist.cgi</code></h3>
<pre>
sub utype {
  local($_) = @_;
  local(%T) = (
    0010000, &#039;PIPE&#039;,
    0020000, &#039;CHR&#039;,
    0040000, &#039;DIR&#039;,
    0060000, &#039;BLK&#039;,
    0100000, &#039;FILE&#039;,
    0120000, &#039;LINK&#039;,
    0140000, &#039;SOCK&#039;,
  );
  return $T{($_ &amp; 0170000)} || &#039;FILE&#039;;
}
&nbsp;
sub umode {
  local($_) = @_;
  local(%T) = (
    0010000, &#039;p&#039;,
    0020000, &#039;c&#039;,
    0040000, &#039;d&#039;,
    0060000, &#039;b&#039;,
    0100000, &#039;-&#039;,
    0120000, &#039;l&#039;,
    0140000, &#039;s&#039;,
  );
&nbsp;
  return ($T{($_ &amp; 0170000)} || &#039;-&#039;)
     . (($_ &amp; 00400) ? &#039;r&#039; : &#039;-&#039;)
     . (($_ &amp; 00200) ? &#039;w&#039; : &#039;-&#039;)
     . (($_ &amp; 04000) ? &#039;s&#039; :
       (($_ &amp; 00100) ? &#039;x&#039; : &#039;-&#039;))
     . (($_ &amp; 00040) ? &#039;r&#039; : &#039;-&#039;)
     . (($_ &amp; 00020) ? &#039;w&#039; : &#039;-&#039;)
     . (($_ &amp; 02000) ? &#039;s&#039; :
       (($_ &amp; 00010) ? &#039;x&#039; : &#039;-&#039;))
     . (($_ &amp; 00004) ? &#039;r&#039; : &#039;-&#039;)
     . (($_ &amp; 00002) ? &#039;w&#039; : &#039;-&#039;)
     . (($_ &amp; 01000) ? &#039;t&#039; :
       (($_ &amp; 00001) ? &#039;x&#039; : &#039;-&#039;));
}
</pre>

<h3><code>/usr/lib/perl/5.8.4/linux/stat.ph</code></h3>
<pre>
        eval &#039;sub S_IFMT () {00170000;}&#039; unless defined(&amp;S_IFMT);
        eval &#039;sub S_IFSOCK () {0140000;}&#039; unless defined(&amp;S_IFSOCK);
        eval &#039;sub S_IFLNK () {0120000;}&#039; unless defined(&amp;S_IFLNK);
        eval &#039;sub S_IFREG () {0100000;}&#039; unless defined(&amp;S_IFREG);
        eval &#039;sub S_IFBLK () {0060000;}&#039; unless defined(&amp;S_IFBLK);
        eval &#039;sub S_IFDIR () {0040000;}&#039; unless defined(&amp;S_IFDIR);
        eval &#039;sub S_IFCHR () {0020000;}&#039; unless defined(&amp;S_IFCHR);
        eval &#039;sub S_IFIFO () {0010000;}&#039; unless defined(&amp;S_IFIFO);
        eval &#039;sub S_ISUID () {0004000;}&#039; unless defined(&amp;S_ISUID);
        eval &#039;sub S_ISGID () {0002000;}&#039; unless defined(&amp;S_ISGID);
        eval &#039;sub S_ISVTX () {0001000;}&#039; unless defined(&amp;S_ISVTX);
        eval &#039;sub S_ISLNK {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFLNK));
        }&#039; unless defined(&amp;S_ISLNK);
        eval &#039;sub S_ISREG {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFREG));
        }&#039; unless defined(&amp;S_ISREG);
        eval &#039;sub S_ISDIR {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFDIR));
        }&#039; unless defined(&amp;S_ISDIR);
        eval &#039;sub S_ISCHR {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFCHR));
        }&#039; unless defined(&amp;S_ISCHR);
        eval &#039;sub S_ISBLK {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFBLK));
        }&#039; unless defined(&amp;S_ISBLK);
        eval &#039;sub S_ISFIFO {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFIFO));
        }&#039; unless defined(&amp;S_ISFIFO);
        eval &#039;sub S_ISSOCK {
            local($m) = @_;
            eval q(((($m) &amp;  &amp;S_IFMT) ==  &amp;S_IFSOCK));
        }&#039; unless defined(&amp;S_ISSOCK);
        eval &#039;sub S_IRWXU () {00700;}&#039; unless defined(&amp;S_IRWXU);
        eval &#039;sub S_IRUSR () {00400;}&#039; unless defined(&amp;S_IRUSR);
        eval &#039;sub S_IWUSR () {00200;}&#039; unless defined(&amp;S_IWUSR);
        eval &#039;sub S_IXUSR () {00100;}&#039; unless defined(&amp;S_IXUSR);
        eval &#039;sub S_IRWXG () {00070;}&#039; unless defined(&amp;S_IRWXG);
        eval &#039;sub S_IRGRP () {00040;}&#039; unless defined(&amp;S_IRGRP);
        eval &#039;sub S_IWGRP () {00020;}&#039; unless defined(&amp;S_IWGRP);
        eval &#039;sub S_IXGRP () {00010;}&#039; unless defined(&amp;S_IXGRP);
        eval &#039;sub S_IRWXO () {00007;}&#039; unless defined(&amp;S_IRWXO);
        eval &#039;sub S_IROTH () {00004;}&#039; unless defined(&amp;S_IROTH);
        eval &#039;sub S_IWOTH () {00002;}&#039; unless defined(&amp;S_IWOTH);
        eval &#039;sub S_IXOTH () {00001;}&#039; unless defined(&amp;S_IXOTH);
    }
    if(defined(&amp;__KERNEL__)) {
        eval &#039;sub S_IRWXUGO () {( &amp;S_IRWXU| &amp;S_IRWXG| &amp;S_IRWXO);}&#039; unless defined(&amp;S_IRWXUGO);
        eval &#039;sub S_IALLUGO () {( &amp;S_ISUID| &amp;S_ISGID| &amp;S_ISVTX| &amp;S_IRWXUGO);}&#039; unless defined(&amp;S_IALLUGO);
        eval &#039;sub S_IRUGO () {( &amp;S_IRUSR| &amp;S_IRGRP| &amp;S_IROTH);}&#039; unless defined(&amp;S_IRUGO);
        eval &#039;sub S_IWUGO () {( &amp;S_IWUSR| &amp;S_IWGRP| &amp;S_IWOTH);}&#039; unless defined(&amp;S_IWUGO);
        eval &#039;sub S_IXUGO () {( &amp;S_IXUSR| &amp;S_IXGRP| &amp;S_IXOTH);}&#039; unless defined(&amp;S_IXUGO);
        require &#039;linux/types.ph&#039;;
        require &#039;linux/time.ph&#039;;
    }
&nbsp;
</pre>

<p><a href="http://ftp.mozilla.org/pub/mozilla.org/mozilla/releases/mozilla1.8a2/src/mozilla-source-1.8a2.tar.bz2 ">Mozilla-Source 1.8a2</a></p>
<pre>
/* notice that these valuse are octal. */
const PERM_IRWXU = 00700;  /* read, write, execute/search by owner */
const PERM_IRUSR = 00400;  /* read permission, owner */
const PERM_IWUSR = 00200;  /* write permission, owner */
const PERM_IXUSR = 00100;  /* execute/search permission, owner */
const PERM_IRWXG = 00070;  /* read, write, execute/search by group */
const PERM_IRGRP = 00040;  /* read permission, group */
const PERM_IWGRP = 00020;  /* write permission, group */
const PERM_IXGRP = 00010;  /* execute/search permission, group */
const PERM_IRWXO = 00007;  /* read, write, execute/search by others */
const PERM_IROTH = 00004;  /* read permission, others */
const PERM_IWOTH = 00002;  /* write permission, others */
const PERM_IXOTH = 00001;  /* execute/search permission, others */
&nbsp;
const MODE_RDONLY   = 0x01;
const MODE_WRONLY   = 0x02;
const MODE_RDWR     = 0x04;
const MODE_CREATE   = 0x08;
const MODE_APPEND   = 0x10;
const MODE_TRUNCATE = 0x20;
const MODE_SYNC     = 0x40;
const MODE_EXCL     = 0x80;
</pre>


<h3><code>/usr/include/libpng12/png.h</code></h3>
<pre>
/* Transform masks for the high-level interface */
#define PNG_TRANSFORM_IDENTITY       0x0000    /* read and write */
#define PNG_TRANSFORM_STRIP_16       0x0001    /* read only */
#define PNG_TRANSFORM_STRIP_ALPHA    0x0002    /* read only */
#define PNG_TRANSFORM_PACKING        0x0004    /* read and write */
#define PNG_TRANSFORM_PACKSWAP       0x0008    /* read and write */
#define PNG_TRANSFORM_EXPAND         0x0010    /* read only */
#define PNG_TRANSFORM_INVERT_MONO    0x0020    /* read and write */
#define PNG_TRANSFORM_SHIFT          0x0040    /* read and write */
#define PNG_TRANSFORM_BGR            0x0080    /* read and write */
#define PNG_TRANSFORM_SWAP_ALPHA     0x0100    /* read and write */
#define PNG_TRANSFORM_SWAP_ENDIAN    0x0200    /* read and write */
#define PNG_TRANSFORM_INVERT_ALPHA   0x0400    /* read and write */
#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* WRITE only */
</pre>


<h3><code>/usr/lib/python2.4/stat.py</code></h3>
<pre>
# Extract bits from the mode
&nbsp;
def S_IMODE(mode):
    return mode &amp; 07777
&nbsp;
def S_IFMT(mode):
    return mode &amp; 0170000
&nbsp;
# Constants used as S_IFMT() for various file types
# (not all are implemented on all systems)
&nbsp;
S_IFDIR  = 0040000
S_IFCHR  = 0020000
S_IFBLK  = 0060000
S_IFREG  = 0100000
S_IFIFO  = 0010000
S_IFLNK  = 0120000
S_IFSOCK = 0140000
&nbsp;
# Functions to test for each file type
&nbsp;
def S_ISDIR(mode):
    return S_IFMT(mode) == S_IFDIR
&nbsp;
def S_ISCHR(mode):
    return S_IFMT(mode) == S_IFCHR
&nbsp;
def S_ISBLK(mode):
    return S_IFMT(mode) == S_IFBLK
&nbsp;
def S_ISREG(mode):
    return S_IFMT(mode) == S_IFREG
&nbsp;
def S_ISFIFO(mode):
    return S_IFMT(mode) == S_IFIFO
&nbsp;
def S_ISLNK(mode):
    return S_IFMT(mode) == S_IFLNK
&nbsp;
def S_ISSOCK(mode):
    return S_IFMT(mode) == S_IFSOCK
&nbsp;
# Names for permission bits
&nbsp;
S_ISUID = 04000
S_ISGID = 02000
S_ENFMT = S_ISGID
S_ISVTX = 01000
S_IREAD = 00400
S_IWRITE = 00200
S_IEXEC = 00100
S_IRWXU = 00700
S_IRUSR = 00400
S_IWUSR = 00200
S_IXUSR = 00100
S_IRWXG = 00070
S_IRGRP = 00040
S_IWGRP = 00020
S_IXGRP = 00010
S_IRWXO = 00007
S_IROTH = 00004
S_IWOTH = 00002
S_IXOTH = 00001
</pre>


<h3><code>/usr/include/bits/stat.h</code></h3>
<pre>
/* Encoding of the file mode.  */
&nbsp;
#define __S_IFMT        0170000 /* These bits determine file type.  */
&nbsp;
/* File types.  */
#define __S_IFDIR       0040000 /* Directory.  */
#define __S_IFCHR       0020000 /* Character device.  */
#define __S_IFBLK       0060000 /* Block device.  */
#define __S_IFREG       0100000 /* Regular file.  */
#define __S_IFIFO       0010000 /* FIFO.  */
#define __S_IFLNK       0120000 /* Symbolic link.  */
#define __S_IFSOCK      0140000 /* Socket.  */
&nbsp;
/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But
   they do it by enforcing the correct use of the macros.  */
#define __S_TYPEISMQ(buf)  ((buf)-&gt;st_mode - (buf)-&gt;st_mode)
#define __S_TYPEISSEM(buf) ((buf)-&gt;st_mode - (buf)-&gt;st_mode)
#define __S_TYPEISSHM(buf) ((buf)-&gt;st_mode - (buf)-&gt;st_mode)
&nbsp;
/* Protection bits.  */
&nbsp;
#define __S_ISUID       04000   /* Set user ID on execution.  */
#define __S_ISGID       02000   /* Set group ID on execution.  */
#define __S_ISVTX       01000   /* Save swapped text after use (sticky).  */
#define __S_IREAD       0400    /* Read by owner.  */
#define __S_IWRITE      0200    /* Write by owner.  */
#define __S_IEXEC       0100    /* Execute by owner.  */
</pre>



<h3><code>/usr/include/linux/nfs.h</code></h3>
<pre>
#define NFS_FIFO_DEV    (-1)
#define NFSMODE_FMT     0170000
#define NFSMODE_DIR     0040000
#define NFSMODE_CHR     0020000
#define NFSMODE_BLK     0060000
#define NFSMODE_REG     0100000
#define NFSMODE_LNK     0120000
#define NFSMODE_SOCK    0140000
#define NFSMODE_FIFO    0010000
</pre>


<h3><code>/usr/include/linux/nfs3.h</code></h3>
<pre>
#define NFS3_FIFO_DEV           (-1)
#define NFS3MODE_FMT            0170000
#define NFS3MODE_DIR            0040000
#define NFS3MODE_CHR            0020000
#define NFS3MODE_BLK            0060000
#define NFS3MODE_REG            0100000
#define NFS3MODE_LNK            0120000
#define NFS3MODE_SOCK           0140000
#define NFS3MODE_FIFO           0010000
&nbsp;
/* Flags for access() call */
#define NFS3_ACCESS_READ        0x0001
#define NFS3_ACCESS_LOOKUP      0x0002
#define NFS3_ACCESS_MODIFY      0x0004
#define NFS3_ACCESS_EXTEND      0x0008
#define NFS3_ACCESS_DELETE      0x0010
#define NFS3_ACCESS_EXECUTE     0x0020
#define NFS3_ACCESS_FULL        0x003f
</pre>


<h3><code>/usr/include/linux/stat.h</code></h3>
<pre>
#define S_IFMT  00170000
#define S_IFSOCK 0140000
#define S_IFLNK  0120000
#define S_IFREG  0100000
#define S_IFBLK  0060000
#define S_IFDIR  0040000
#define S_IFCHR  0020000
#define S_IFIFO  0010000
#define S_ISUID  0004000
#define S_ISGID  0002000
#define S_ISVTX  0001000
&nbsp;
#define S_ISLNK(m)      (((m) &amp; S_IFMT) == S_IFLNK)
#define S_ISREG(m)      (((m) &amp; S_IFMT) == S_IFREG)
#define S_ISDIR(m)      (((m) &amp; S_IFMT) == S_IFDIR)
#define S_ISCHR(m)      (((m) &amp; S_IFMT) == S_IFCHR)
#define S_ISBLK(m)      (((m) &amp; S_IFMT) == S_IFBLK)
#define S_ISFIFO(m)     (((m) &amp; S_IFMT) == S_IFIFO)
#define S_ISSOCK(m)     (((m) &amp; S_IFMT) == S_IFSOCK)
&nbsp;
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
&nbsp;
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
&nbsp;
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
</pre>











<h2>Further File Permissions Reading</h2>
<h3>Related PHP Functions</h3>
<ul>
<li><a href="http://php.net/manual/en/function.fileperms.php">fileperms</a></li>
<li><a href="http://php.net/manual/en/function.stat.php">stat</a></li>
<li><a href="http://php.net/manual/en/function.chmod.php">chmod</a></li>
<li><a href="http://php.net/manual/en/function.clearstatcache.php">clearstatcache</a></li>
<li><a href="http://php.net/manual/en/function.chown.php">chown</a></li>
<li><a href="http://php.net/manual/en/function.chgrp.php">chgrp</a></li>
<li><a href="http://php.net/manual/en/function.lchown.php">lchown</a></li>
<li><a href="http://php.net/manual/en/function.lchgrp.php">lchgrp</a></li>
<li><a href="http://php.net/manual/en/function.touch.php">touch</a></li>
<li><a href="http://php.net/manual/en/function.lstat.php">lstat</a></li>
<li><a href="http://php.net/manual/en/function.fstat.php">filestat</a></li>
<li><a href="http://php.net/manual/en/function.fileatime.php">fileatime</a></li>
<li><a href="http://php.net/manual/en/function.filectime.php">filectime</a></li>
<li><a href="http://php.net/manual/en/function.filegroup.php">filegroup</a></li>
<li><a href="http://php.net/manual/en/function.fileinode.php">fileinode</a></li>
<li><a href="http://php.net/manual/en/function.filemtime.php">filemtime</a></li>
<li><a href="http://php.net/manual/en/function.fileowner.php">fileowner</a></li>
<li><a href="http://php.net/manual/en/function.filesize.php">filesize</a></li>
<li><a href="http://php.net/manual/en/function.filetype.php">filetype</a></li>
<li><a href="http://php.net/manual/en/function.is-writable.php">is_writable</a></li>
<li><a href="http://php.net/manual/en/function.is-readable.php">is_readable</a></li>
<li><a href="http://php.net/manual/en/function.is-executable.php">is_executable</a></li>
<li><a href="http://php.net/manual/en/function.is-file.php">is_file</a></li>
<li><a href="http://php.net/manual/en/function.is-dir.php">is_dir</a></li>
<li><a href="http://php.net/manual/en/function.is-link.php">is_link</a></li>
<li><a href="http://php.net/manual/en/function.file-exists.php">file_exists</a></li>
<li><a href="http://php.net/manual/en/function.disk-total-space.php">disk_total_space</a></li>
<li><a href="http://php.net/manual/en/function.disk-free-space.php">disk_free_space</a></li>
</ul>


<h3>Special file types</h3>
<ul>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#link-invocation">link invocation</a>:  Make a hard link via the link syscall</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#ln-invocation">ln invocation</a>: Make links between files</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#mkdir-invocation">mkdir invocation</a>: Make directories</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#mkfifo-invocation">mkfifo invocation</a>: Make FIFOs (named pipes)</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#mknod-invocation">mknod invocation</a>: Make block or character special files</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#readlink-invocation">readlink invocation</a>: Print the referent of a symbolic link</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#rmdir-invocation">rmdir invocation</a>: Remove empty directories</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#unlink-invocation">unlink invocation</a>: Remove files via unlink syscall</li>
</ul>


<h3>Changing file attributes</h3>
<ul>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#chown-invocation">chown invocation</a>: Change file owner and group</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#chgrp-invocation">chgrp invocation</a>: Change group ownership</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#chmod-invocation">chmod invocation</a>: Change access permissions</li>
<li><a href="http://www.gnu.org/software/coreutils/manual/coreutils.html#touch-invocation">touch invocation</a>: Change file timestamps</li>
</ul><p><a href="http://www.askapache.com/security/chmod-stat.html"></a><a href="http://www.askapache.com/security/chmod-stat.html">Chmod, Umask, Stat, Fileperms, and File Permissions</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/security/chmod-stat.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Dealing with Mobile Visitors using Bad Browsers</title>
		<link>http://www.askapache.com/htaccess/dealing-mobile-browsers.html</link>
		<comments>http://www.askapache.com/htaccess/dealing-mobile-browsers.html#comments</comments>
		<pubDate>Fri, 10 Sep 2010 00:26:35 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=4508</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/htaccess/dealing-mobile-browsers.html"></a><a href="http://www.askapache.com/htaccess/dealing-mobile-browsers.html"><cite>AskApache.com</cite></a></p><a href="http://perishablepress.com/press/2010/04/26/stop-404-requests-for-mobile-versions-of-your-site/">Definately worth the read</a>, but it is hard to see any benefit to doing this.

Mobile agents are still in their infancy, but within 2 years most mobiles will be as fast as the laptops from a couple years back... I mean my droid is running linux!  The world is moving steadily towards a society where mobile devices will greatly outnumber pcs.  So during this "growing up" phase I would argue that it would be much more beneficial to look for a method that solves the resource-robbing issue from the server-side, while also keeping in mind that mobile visitors to your site will continue to grow and eventually surpass non-mobile clients.

It definately makes it harder to understand the reasons behind this clever post without having more information on the mobile bots that you've been seeing in your logs..  Obviously (looking at your impressive blacklist work) that would be easy for you to get, but it would help us to see the same thing.

Alot of mobile devices have very small amounts of memory, especially smal is the amount of storage available to save data too.  In approaching that significant problem from a programming point of view, programmers built the mobile user-agents to be as fast as possible using minimal data.   Knowing that it makes sense for a mobile agent to try hard to find an alternate version of a page formatted with it's unique lack of resources in mind.  Issuing 100 requests for non-existant pages and only finding the right one on the 100th try would almost certainly be worth it for a mobile device.  Most devices use socket programming to communicate across HTTP for speed, which makes it very quick and easy to issue requests..  Basically they are free in terms of what it takes to make a request.  unfortunately this would really take up some cpu/memory/connections on our servers if they aren't setup and optimized.   1000 mobiles doing this simultaneously would grind most sites to a halt.

The solution you came up with would definately help that situation.  403's are the strongest method available to a server (at least in terms of the HTTP protocol) to tell a useragent to get gone.   They are also the best way (at least in apache) to save your cpu/resources as a 403 causes apache internally to end the connection, clean up it's internal data structures, and terminate the actual connection and apache processing of the request.

However 403's are too strict for a situation without any clear abuse going on, 403's are understood by all agents and can do some bad things to your site if used like this.  You can get dropped from search indexes for returning 403's (thats google trying to do you a favor by not indexing "Forbidden" content), and I've found that returning a 403 to crawlers causes them to sometimes retry in 15min, then an hour, then a day, then a week, and the spaces between checks grow until they stop.

Oh ya, it is very unlikely that a mobile device will save the results of non-existing mobile uris, mostly because it doesn't cost them anything to make it (unless you setup a trap like mod_security that lets you respond byte by byte veryyyyy slowwwwlyyyy).   And even then mobile devices do not have that kind of memory to store lists of requested urls and their responses.  Think about it, to check if the url returned a bad result previously before making the same request would very very quickly freeze up a device, 50 sites x 5 requests and responses equals quite a bit of data, not to mention having to then search through all that data before making a request.. the battery would die super fast.

This is also the primary reason that the new AMAZINGLY fast opera browser released last month for the droid does what it does.  It uses socket-level HTTP like everyone else, but opera setup mobile proxy servers around the nation to act as the intermediarys and crunch the actual data for the mobile.   There just isn't enough mem for my droid to be able to open a huge webpage, parse the source, and then render it, so it looks for mobile versions whenever possible.  If it can't find a mobile version or the mobile version is still too big, it proxies the request across a mobile proxy server (such as used by google, opera, blackberry) which allows the proxy server (super sophisticated) to get the content first, render it, and then send it to your mobile for direct viewing.   More than proxy servers they act as caches.  And especially due to the fact they all use custom programming (the proxies) you do not want to play around with HTTP 403's like that.  It could easily have the effect of blocking a root proxy resulting in your site being blocked by the entire proxy and it's clients.  Unlike mobiles, those machines store request state info extremely well.


Regarding a 410, that seems like a great solution but actually could be the worst possible thing to do.  410 gone means it used to exist, and also means that it was removed purposefully and will NEVER be available again.   2 years from now when googles mobile index takes over the main web index, you will be upstream without a paddle, with no clue as to why your new mobile area isn't getting traffic.

Very few useragents understand a 410, it's one of those codes used almost exclusively for controlling the way search engines index your content.  So to me it makes no sense to issue an esoteric status code to a bot that doesn't even understand 404's.

The only time you should ever have to use a 410 is when you make a big mistake with your indexing and have to use it to fix your site index.  Many other useragents have minimal understanding of HTTP (esp bots, crawlers, spammers, etc) either by design for speed or whatever..  they just look at the first digit of the response code (2 OK, 3 REDIRECT, 4 NOT EXIST, 5 SERVER ERROR) and determine from that alone whether the content is good or not.

Basically all mobile devices run on HTTP 1.1, but for their own physical limitations they behave like HTTP 1.0 clients from a server admin standpoint.<p><a href="http://www.askapache.com/htaccess/dealing-mobile-browsers.html"></a><a href="http://www.askapache.com/htaccess/dealing-mobile-browsers.html">Dealing with Mobile Visitors using Bad Browsers</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/dealing-mobile-browsers.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Advanced WordPress wp-config.php Tweaks</title>
		<link>http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html</link>
		<comments>http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html#comments</comments>
		<pubDate>Wed, 03 Mar 2010 08:23:37 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3341</guid>
		<description><![CDATA[<p>The bottom line for this article is that I want to make WordPress as fast, secure, and easy to install, run, and manage because I am using it more and more for client production sites, I will work for days in order to solve an issue so that I never have to spend time on that issue again. Time is money in this industry and that is ultimately (time) what there is to gain by tweaking WordPress.</p>

<p class="cnote"><strong>Note:</strong> I spent no time on readability, this is primarily a read the code and figure it out article.. This is for advanced users looking for a reference or discussion and for those of you looking to advance.  Feedback would be great <em>if you make it that far..</em></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html"></a><a href="http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html"><cite>AskApache.com</cite></a></p><p>The bottom line for this article is that I want to make WordPress as fast, secure, and easy to install, run, and manage because I am using it more and more for client production sites, I will work for days in order to solve an issue so that I never have to spend time on that issue again. Time is money in this industry and that is ultimately (time) what there is to gain by tweaking WordPress.</p>
<p class="cnote"><strong>Note:</strong> I spent no time on readability, this is primarily a read the code and figure it out article.. This is for advanced users looking for a reference or discussion and for those of you looking to advance.  Feedback would be great <em>if you make it that far..</em></p>
<p>For a better handle on the way I like to structure web site directories, see <a href="http://www.askapache.com/htaccess/optimize-website-files-cache-security.html">Optimize a Website for Speed, Security, and Easy Management</a> but note it is a bit outdated compared to what I'm doing now.  I don't have the luxury of using only one type of server, or hosting provider anymore, so I have been working towards making things even more portable in order to move from host to host from server to server without issues i.e. my portable <a href="http://www.askapache.com/linux/bash_profile-functions-advanced-shell.html">.bash_profile</a>.</p>
<p>So I've been basically experimenting various ways to accomplish that and thought I would share what I am currently doing for my benefit and hopefully get some input.  All of my WP installs run the development version, and one main idea with my setups is that upgrading is automated.  So I really keep the WordPress install clean and use plugins and wp-config.php to do all the customization.</p>
<ul>
    <li>Portability - Hands-free upgrades and easy to move</li>
    <li>Security - Additional security and protection</li>
    <li>Speed - Less CPU and Disk I/O</li>
    <li>Customization - All my favorite customizations</li>
</ul>
<h2>wp-config.php</h2>
<p>These are the main settings I use.. Seriously this is more like an interactive article, because to understand it you will need to do some code grepping.  You may want to grab a jolt.</p>
<h3>ASKAPACHE_ROOT</h3>
<p>The ASKAPACHE_ROOT variable is just a better way for me to be able to include and access all the different files in my site tree.  For instance, in my non-wp php files, I can do this:</p>
<pre>!defined(&#039;ASKAPACHE_ROOT&#039;) &amp;&amp; require $_SERVER[&#039;DOCUMENT_ROOT&#039;] . &#039;/wp-config.php&#039;;
include(ASKAPACHE_ROOT . &#039;/includes/custom-download.inc.php&#039;);</pre>
<h3>ASKAPACHE_LOCK</h3>
<p>This is one of my all-time favorite hacks, that I think is one of the most useful methods I employ as a web developer.  This allows me to use far-future-expire headers for optimum caching, while still forcing browsers to re-validate every day or so automatically, or forcing them to re-validate whenever I change the suffix.  This takes advantage of the <a href="http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html">mod_rewrite trick</a> that I use on EVERY site I run, definately worth learning. Because I practice best-practice web-standards, for every web site I create a single css file and javascript file, which I then add to the template like:</p>
<pre>&lt;link rel="stylesheet" type="text/css" media="all" href="http://static.askapache.com/c/apache-0&lt;?php echo ASKAPACHE_LOCK?&gt;.css" /&gt;
&lt;script src="http://static.askapache.com/j/apache-0&lt;?php echo ASKAPACHE_LOCK;?&gt;.js" type="text/javascript"&gt;&lt;/script&gt;</pre>
<pre>&lt;?php
/**
 * The base configurations of the WordPress.
 *
 * This file has the following configurations: MySQL settings, Table Prefix,
 * Secret Keys, WordPress Language, and ABSPATH. You can find more information by
 * visiting {@link http://codex.wordpress.org/Editing_wp-config.php Editing
 * wp-config.php} Codex page. You can get the MySQL settings from your web host.
 *
 * This file is used by the wp-config.php creation script during the
 * installation. You don&#039;t have to use the web site, you can just copy this file
 * to "wp-config.php" and fill in the values.
 *
 * @package WordPress
 */
/* http://codex.wordpress.org/Editing_wp-config.php */
&nbsp;
/** /home/liet/askapache.com */
!defined(&#039;ASKAPACHE_ROOT&#039;) &amp;&amp; define(&#039;ASKAPACHE_ROOT&#039;, str_replace(&#039;/public_html&#039;,&#039;&#039;, $_SERVER[&#039;DOCUMENT_ROOT&#039;]));
&nbsp;
/** The 008 at the end is for manual tweaking.  time() returns seconds since &#039;00:00:00 1970-01-01 UTC&#039;. */
// http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files.html
!defined(&#039;ASKAPACHE_LOCK&#039;) &amp;&amp; define(ASKAPACHE_LOCK&#039;, substr(time(),0,5).&#039;008&#039;); // 12533001
&nbsp;
/** absolute path to the WordPress directory */
!defined(&#039;ABSPATH&#039;) &amp;&amp; define(&#039;ABSPATH&#039;, ASKAPACHE_ROOT .&#039;/public_html/&#039;);
&nbsp;
/**
 * WP_SITEURL, defined since WordPress Version 2.2, allows the WordPress address (URL) to be defined. The valued defined is the address where your WordPress core files reside.
 * It should include the http:// part too. Do not put a slash "/" at the end.
 * Setting this value in wp-config.php overrides the wp_options table value for siteurl and disables the WordPress address (URL) field in the Administration &gt; Settings &gt; General panel.
 */
!defined(&#039;WP_SITEURL&#039;) &amp;&amp; define(&#039;WP_SITEURL&#039;, &#039;http://&#039;.$_SERVER[&#039;SERVER_NAME&#039;]);
&nbsp;
/**
 * WP_HOME is another wp-config.php option added in WordPress Version 2.2. Similar to WP_SITEURL,
 * WP_HOME overrides the wp_options table value for home but does not change it permanently.
 * home is the address you want people to type in their browser to reach your WordPress blog. It should include the http:// part. Also, do not put a slash "/" at the end.
 */
!defined(&#039;WP_HOME&#039;) &amp;&amp; define(&#039;WP_HOME&#039;, WP_SITEURL);
&nbsp;
/** no trailing slash, full paths only */
!defined(&#039;WP_CONTENT_DIR&#039;) &amp;&amp; define( &#039;WP_CONTENT_DIR&#039;, ABSPATH . &#039;wp-content&#039; );
&nbsp;
// full url - WP_CONTENT_DIR is defined further up
!defined(&#039;WP_CONTENT_URL&#039;) &amp;&amp; define( &#039;WP_CONTENT_URL&#039;, WP_SITEURL . &#039;/wp-content&#039;);
&nbsp;
/** Allows for the plugins directory to be moved from the default location. @since 2.6.0 */
// full path, no trailing slash
!defined(&#039;WP_PLUGIN_DIR&#039;) &amp;&amp; define( &#039;WP_PLUGIN_DIR&#039;, WP_CONTENT_DIR . &#039;/plugins&#039; );
&nbsp;
/** Allows for the plugins directory to be moved from the default location. @since 2.6.0 */
// full url, no trailing slash
!defined(&#039;WP_PLUGIN_URL&#039;) &amp;&amp; define( &#039;WP_PLUGIN_URL&#039;, WP_CONTENT_URL . &#039;/plugins&#039; );
&nbsp;
/** Allows for the plugins directory to be moved from the default location. @since 2.1.0 */
// Relative to ABSPATH.  For back compat.
//!defined(&#039;PLUGINDIR&#039;) &amp;&amp; define( &#039;PLUGINDIR&#039;, &#039;wp-content/plugins&#039; );
&nbsp;
/** Number of autosaves to save. TRUE is default and enables post revisions, FALSE disables revisions completely. */
!defined(&#039;WP_POST_REVISIONS&#039;) &amp;&amp; define(&#039;WP_POST_REVISIONS&#039;, 150);
&nbsp;
/* ini_set(&#039;memory_limit&#039;, WP_MEMORY_LIMIT); */
!defined(&#039;WP_MEMORY_LIMIT&#039;) &amp;&amp; define(&#039;WP_MEMORY_LIMIT&#039;, &#039;64M&#039;);
&nbsp;
/** Only check at this interval for new messages. Default is 5min */
/** @since 2.9  */
!defined(&#039;WP_MAIL_INTERVAL&#039;) &amp;&amp; define(&#039;WP_MAIL_INTERVAL&#039;, 3600); // 1 hour
&nbsp;
/** Saves updated post values to post from edit window every x seconds. (default 60)
 * When editing a post, WordPress uses Ajax to auto-save revisions to the post as you edit. You may want to increase this setting for longer delays in between auto-saves, or decrease the setting to make sure you never lose changes.
 * @since 2.5.0 */
!defined( &#039;AUTOSAVE_INTERVAL&#039; ) &amp;&amp; define( &#039;AUTOSAVE_INTERVAL&#039;, 60 );
&nbsp;
/** @since 2.9.0  */
/** Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS. */
!defined( &#039;EMPTY_TRASH_DAYS&#039; ) &amp;&amp; define( &#039;EMPTY_TRASH_DAYS&#039;, 300 );</pre>
<hr class="C" />
<h2>Debugging WordPress</h2>
<p>One of my secrets for getting really good at this stuff is to master debugging.  There is really not ever a time when I am working on a site that I don't have <a href="http://www.askapache.com/security/elite-log-file-scrolling-with-color-syntax.html">color-highlighted logs scrolling automatically in an ssh window</a>.  It's really almost impossible to fix problems with wordpress or do any kind of advanced anything without being able to view debugging info.  At first I relied heavily on a <a href="http://www.askapache.com/php/custom-phpini-tips-and-tricks.html">custom php.ini</a> being available on the server, but after having to deal with many hosts who don't allow <code>php.ini</code> files I now rely completely on setting values using <a href="http://php.net/manual/en/function.ini-set.php">ini_set</a> for ultimate portability. Detailed towards the end of this article and is also included in this <code>wp-config.php</code></p>
<pre>/**#@+
 * DEBUGGING STUFF
 */
/** display of notices during development. if false, error_reporting is E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR otherwise E_ALL */
!defined(&#039;WP_DEBUG&#039;) &amp;&amp; define(&#039;WP_DEBUG&#039;, false);
&nbsp;
/** The SAVEQUERIES definition saves the database queries to a array and that array can be displayed to help analyze those queries.
 *  The information saves each query, what function called it, and how long that query took to execute.  */
!defined(&#039;SAVE_QUERIES&#039;) &amp;&amp; define(&#039;SAVE_QUERIES&#039;, WP_DEBUG);
&nbsp;
!defined(&#039;ACTION_DEBUG&#039;) &amp;&amp; define(&#039;ACTION_DEBUG&#039;, WP_DEBUG);
&nbsp;
/** This will allow you to edit the scriptname.dev.js files in the wp-includes/js and wp-admin/js directories.  */
!defined(&#039;SCRIPT_DEBUG&#039;) &amp;&amp; define(&#039;SCRIPT_DEBUG&#039;, WP_DEBUG);
&nbsp;
/** Add define(&#039;WP_DEBUG_LOG&#039;, true); to enable php debug logging to WP_CONTENT_DIR/debug.log */
//!defined(&#039;WP_DEBUG_LOG&#039;) &amp;&amp; define(&#039;WP_DEBUG_LOG&#039;, true);
&nbsp;
/** This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user.
 *  Add define(&#039;WP_DEBUG_DISPLAY&#039;, false); to wp-config.php to use the globally configured setting for display_errors and not force it to On */
!defined(&#039;WP_DEBUG_DISPLAY&#039;) &amp;&amp; define(&#039;WP_DEBUG_DISPLAY&#039;, false);</pre>
<hr class="C" />
<h2>Ultimate Security Tweaks</h2>
<p>Well, ultimate for WP's built-in keys and password functions, this is all for wp-config.php keep in mind.  This is a very neccessary and recommended step, and is one of the only things I modify for each new installation.</p>
<h3>Security KEYS</h3>
<p>If like me you are familiar with password-cracking software like John the ripper, rainbow hash tables, l0pht-crack, etc.. then you will like to know that you can specify your own keys and salts for the encryption used by WP.  They are <code>AUTH_KEY</code>, <code>AUTH_SALT</code>, <code>SECURE_AUTH_KEY</code>, <code>SECURE_AUTH_SALT</code>, <code>LOGGED_IN_KEY</code>, <code>LOGGED_IN_SALT</code>, <code>NONCE_KEY</code>, <code>NONCE_SALT</code>, <code>SECRET_KEY</code> and <code>SECRET_SALT</code>.</p>
<p>A random and long key gives you better encryption, and exponentially increasing that is using a random and long salt for the encryption.  Encryptions with known salts are incredibly easy to decrypt compared to encryptions with secure salts, because the salt + key individually need to be guessed in order to find a matching hash, vs. just the key if the salt is known.  See: <a href="http://www.askapache.com/security/locating-weak-passwords.html">Locating weak passwords</a>.</p>
<blockquote>
    <p>A secret key is a hashing salt which makes your site harder to hack and access harder to crack by adding random elements to the password.</p>
    <p>In simple terms, a secret key is a password with elements that make it harder to generate enough options to break through your security barriers. A password like "password" or "test" is simple and easily broken. A random, unpredictable password such as "88a7da62429ba6ad3cb3c76a09641fc" takes years to come up with the right combination.</p>
</blockquote>
<p>For more information on the technical background and breakdown of secret keys and secure passwords, see: </p>
<ul>
    <li><a href="http://wordpress.org/support/topic/170987">WordPress Support Forum - HOWTO: Set up secret keys in WordPress 2.6+</a></li>
    <li><a href="http://en.wikipedia.org/wiki/Password_cracking">Wikipedia's explanation of Password Cracking</a></li>
</ul>
<p>I like to use the <a href="https://api.wordpress.org/secret-key/1.1/">WordPress.org secret-key service</a> 4 times.  That's because for each key and salt I like to do: (1 key from api +random keyboard input+1 key from api).</p>
<pre>/**#@+
 * Authentication Unique Keys.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 *
 * Get salt to add to hashes to help prevent attacks.
 *
 * The secret key is located in two places: the database in case the secret key
 * isn&#039;t defined in the second place, which is in the wp-config.php file. If you
 * are going to set the secret key, then you must do so in the wp-config.php
 * file.
 *
 * The secret key in the database is randomly generated and will be appended to
 * the secret key that is in wp-config.php file in some instances. It is
 * important to have the secret key defined or changed in wp-config.php.
 *
 * If you have installed WordPress 2.5 or later, then you will have the
 * SECRET_KEY defined in the wp-config.php already. You will want to change the
 * value in it because hackers will know what it is. If you have upgraded to
 * WordPress 2.5 or later version from a version before WordPress 2.5, then you
 * should add the constant to your wp-config.php file.
 *
 * Below is an example of how the SECRET_KEY constant is defined with a value.
 * You must not copy the below example and paste into your wp-config.php. If you
 * need an example, then you can have a
 * {@link https://api.wordpress.org/secret-key/1.1/ secret key created} for you.
 *
 * Salting passwords helps against tools which has stored hashed values of
 * common dictionary strings. The added values makes it harder to crack if given
 * salt string is not weak.
 *
 * @since 2.5
 * @link https://api.wordpress.org/secret-key/1.1/ Create a Secret Key for wp-config.php
 *
 * @return string Salt value from either &#039;SECRET_KEY&#039; or &#039;secret&#039; option
 */
define(&#039;AUTH_KEY&#039;,        &#039;jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?p[B+GR{@&gt;{Yq`c|LnG;dvq#| %OA_cbBSU6,rICC1o/c)-|&#039;);
define(&#039;SECURE_AUTH_KEY&#039;, &#039;jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[Bb15baar8&amp;R-r&lt;[T|?(xhJJABGq+Ux+U$)-Hltp/&#039;);
define(&#039;LOGGED_IN_KEY&#039;,   &#039;jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[B&lt;5n6DG|YWnJ9tY2!M1L)`{-$LW~~Ia%.uCbn!P. 41o2$Z$4&#039;);
define(&#039;NONCE_KEY&#039;,       &#039;jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[Bgu&lt;wM*zewR0.{+m:bmrB?wj!B,4]Wo+4 Avk ApR-D?E&#039;);
define(&#039;SECRET_KEY&#039;,     &#039;jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[B52ugH6muE9r4._iZwoYKUybrqLPpv|d Xr+|yrqhUE&#039;);
&nbsp;
define(&#039;AUTH_SALT&#039;,        &#039;123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdm~Ky%+%~PPa5b YEmDI%U[W!-B&#039;);
define(&#039;SECURE_AUTH_SALT&#039;, &#039;123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmad/7o6.AU3%9o-|Kqm]+eUqr-n~:ag&#039;);
define(&#039;LOGGED_IN_SALT&#039;,   &#039;123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmsLiCv@KJ{#wd(?qe(KcH3!&#039;);
define(&#039;NONCE_SALT&#039;,       &#039;123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmG9&gt;+wm 2)bS0Pd_+1rx0brX]ND8|&#039;);
define(&#039;SECRET_SALT&#039;,      &#039;123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdm2&lt;&gt;))U|sty)+4vpWooKls/^[vN&#039;);
/**#@-*/</pre>
<hr class="C" />
<h2>Using SSL for Admin and Login</h2>
<p>SSL is kinda required from my point of view, it is just way to easy to sniff data off the wire otherwise.  At least with SSL you force them to use tools like burpsuite, paros proxy, webscarab, etc..</p>
<pre>/** @since 2.6.0  */
!defined(&#039;FORCE_SSL_ADMIN&#039;) &amp;&amp; define(&#039;FORCE_SSL_ADMIN&#039;, true);
&nbsp;
/** @since 2.6.0  */
!defined(&#039;FORCE_SSL_LOGIN&#039;) &amp;&amp; define(&#039;FORCE_SSL_LOGIN&#039;, true);</pre>
<h3>Mod_Rewrite to Force SSL</h3>
<p>This is pretty cool, it forces non-https for all urls except for /wp-admin and wp-login.php, which both require https.  It also checks for the logged_in_cookie, and if that is present in the request then it doesn't force non-https.  Kinda confusing if you don't have a <a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">mod_rewrite cheatsheet</a>.</p>
<pre>RewriteCond %{THE_REQUEST} ^$ [OR]
RewriteCond %{REQUEST_URI} ^/(wp-admin|wp-login\.php).*$ [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*wp_li_sadfsdfasdf11b361cdsdfasdfasd=.*$ [NC]
RewriteRule .* - [S=1]
&nbsp;
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{HTTP_HOST} !^www\.askapache\.com$ [NC]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
&nbsp;
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(wp-admin/.*|wp-login\.php.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]</pre>
<hr class="C" />
<h2>File System Permissions</h2>
<p><a class="IFR" href="http://www.askapache.com/security/chmod-umask-fileperms-stat-tricks.html"><img src="http://uploads.askapache.com/2008/11/danger-chmod-screenshot.png" alt="chmod, umask, file permissions test" title="chmod, umask, file permissions test" /></a>You can get a basic and solid intro on file permissions by reading: <a href="http://codex.wordpress.org/Changing_File_Permissions">Changing File Permissions</a>, or you can check out some of my <a href="http://www.askapache.com/security/chmod-umask-fileperms-stat-tricks.html">file permission research</a>.<br class="C" />
</p>
<pre>/** The permissions as octal number, usually 0644 for files, 0755 for dirs.
 *  http://codex.wordpress.org/Changing_File_Permissions
 *  if ( !$wp_filesystem-&gt;mkdir($remote_destination, FS_CHMOD_DIR) )
 */
!defined(&#039;FS_CHMOD_DIR&#039;) &amp;&amp; define(&#039;FS_CHMOD_DIR&#039;, (0755 &amp; ~ umask()));
!defined(&#039;FS_CHMOD_FILE&#039;) &amp;&amp; define(&#039;FS_CHMOD_FILE&#039;, (0644 &amp; ~ umask()));
/**#@-*/
&nbsp;
/** Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default. */
//stream_set_timeout( $stream, FS_TIMEOUT );
//!defined(&#039;FS_TIMEOUT&#039;) &amp;&amp; define(&#039;FS_TIMEOUT&#039;, 30);
&nbsp;
//$this-&gt;link = @ftp_connect($this-&gt;options[&#039;hostname&#039;], $this-&gt;options[&#039;port&#039;], FS_CONNECT_TIMEOUT);
//!defined(&#039;FS_CONNECT_TIMEOUT&#039;) &amp;&amp; define(&#039;FS_CONNECT_TIMEOUT&#039;, 30);
&nbsp;
// function get_filesystem_method($args = array(), $context = false) {
//  $method = defined(&#039;FS_METHOD&#039;) ? FS_METHOD : false; //Please ensure that this is either &#039;direct&#039;, &#039;ssh&#039;, &#039;ftpext&#039; or &#039;ftpsockets&#039;
//!defined(&#039;FS_METHOD&#039;) &amp;&amp; define(&#039;FS_METHOD&#039;, &#039;direct&#039;);
&nbsp;
/** These methods for the WordPress core, plugin, and theme upgrades try to determine the WordPress path, as reported by PHP, but symlink trickery can sometimes
 * &#039;muck this up&#039; so if you know the paths to the various folders on the server, as seen via your FTP user, you can manually define them in the wp-config.php file.
 * FS_METHOD forces the filesystem method. It should only be "direct", "ssh", "ftpext", or "ftpsockets".
 * FTP_BASE is the full path to the "base" folder of the WordPress installation.
 * FTP_CONTENT_DIR is the full path to the wp-content folder of the WordPress installation.
 * FTP_PLUGIN_DIR is the full path to the plugins folder of the WordPress installation.
 * FTP_PUBKEY is the full path to your SSH public key.
 * FTP_PRIKEY is the full path to your SSH private key.
 * FTP_USER is either user FTP or SSH username. Most likely these are the same, but use the appropriate one for the type of update you wish to do.
 * FTP_PASS is the password for the username entered for FTP_USER. If you are using SSH public key authentication this can be omitted.
 * FTP_HOST is the hostname:port combination for your SSH/FTP server. The standard FTP port is 21 and the standard SSH port is 22.
 */
//define(&#039;FS_METHOD&#039;, &#039;ftpext&#039;);
//define(&#039;FTP_BASE&#039;, &#039;/path/to/wordpress/&#039;);
//define(&#039;FTP_CONTENT_DIR&#039;, &#039;/path/to/wordpress/wp-content/&#039;);
//define(&#039;FTP_PLUGIN_DIR &#039;, &#039;/path/to/wordpress/wp-content/plugins/&#039;);
//define(&#039;FTP_PUBKEY&#039;, &#039;/home/username/.ssh/id_rsa.pub&#039;);
//define(&#039;FTP_PRIKEY&#039;, &#039;/home/username/.ssh/id_rsa&#039;);
//define(&#039;FTP_USER&#039;, &#039;username&#039;);
//define(&#039;FTP_PASS&#039;, &#039;password&#039;);
//define(&#039;FTP_HOST&#039;, &#039;ftp.example.org:21&#039;);
&nbsp;
/**
 * Block requests through the proxy.
 *
 * Those who are behind a proxy and want to prevent access to certain hosts may do so. This will
 * prevent plugins from working and core functionality, if you don&#039;t include api.wordpress.org.
 *
 * You block external URL requests by defining WP_HTTP_BLOCK_EXTERNAL in your wp-config.php file
 * and this will only allow localhost and your blog to make requests.
 * The constant WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the
 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow.
 *
 * @since 2.8.0
 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests.
/** @since 2.9  */
//!defined(&#039;WP_HTTP_BLOCK_EXTERNAL&#039;) &amp;&amp; define( &#039;WP_HTTP_BLOCK_EXTERNAL&#039;, false );
&nbsp;
/*
 * The constant WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the
 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow.
 *
 * @since 2.8.0
 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests.
 * $accessible_hosts = preg_split(&#039;|,\s*|&#039;, WP_ACCESSIBLE_HOSTS);
 * return !in_array( $check[&#039;host&#039;], $accessible_hosts ); //Inverse logic, If its in the array, then we can&#039;t access it.
 */
//!defined(&#039;WP_ACCESSIBLE_HOSTS&#039;) &amp;&amp; define( &#039;WP_ACCESSIBLE_HOSTS&#039;, &#039;askapache.com,askapache.org&#039; );</pre>
<hr class="C" />
<h3>Cookies!</h3>
<p>There's always a little comfort in having non-default cookies for security (against auto-bots), and using shorter names also means smaller HTTP Packets.</p>
<p>The <code>$cookie_hash</code> is my hack to get around the fact that <code>COOKIEHASH</code> isn't definable in <code>wp-config</code>.</p>
<pre>/**#@+
 * COOKIES
 * Used to guarantee unique hash cookies @since 1.5 */
$cookie_hash=md5(WP_SITEURL);
&nbsp;
/** Set a cookie now to see if they are supported by the browser.
 * setcookie(TEST_COOKIE, &#039;WP Cookie check&#039;, 0, COOKIEPATH, COOKIE_DOMAIN);
 * @since 2.3.0 */
!defined(&#039;TEST_COOKIE&#039;) &amp;&amp; define(&#039;TEST_COOKIE&#039;, &#039;wp_tc&#039;);
&nbsp;
/* @since 2.6.0 */
!defined(&#039;LOGGED_IN_COOKIE&#039;) &amp;&amp; define(&#039;LOGGED_IN_COOKIE&#039;, &#039;wp_li_&#039; . $cookie_hash);
&nbsp;
/* @since 2.6.0 */
!defined(&#039;SECURE_AUTH_COOKIE&#039;) &amp;&amp; define(&#039;SECURE_AUTH_COOKIE&#039;, &#039;wp_sa_&#039; . $cookie_hash);
&nbsp;
/* @since 2.5.0 */
!defined(&#039;AUTH_COOKIE&#039;) &amp;&amp; define(&#039;AUTH_COOKIE&#039;, &#039;wp_a_&#039; . $cookie_hash);
&nbsp;
/* @since 2.0.0 */
!defined(&#039;PASS_COOKIE&#039;) &amp;&amp; define(&#039;PASS_COOKIE&#039;, &#039;wp_p_&#039; . $cookie_hash);
&nbsp;
/* @since 2.0.0 */
!defined(&#039;USER_COOKIE&#039;) &amp;&amp; define(&#039;USER_COOKIE&#039;, &#039;wp_u_&#039; . $cookie_hash);
&nbsp;
/* ok unset this var, its not needed as COOKIEHASH will have this value, but is not definable in wp-config.php */
unset($cookie_hash);
&nbsp;
/** @since 1.2.0 */
!defined(&#039;COOKIEPATH&#039;) &amp;&amp; define(&#039;COOKIEPATH&#039;, preg_replace(&#039;|https?://[^/]+|i&#039;, &#039;&#039;, WP_HOME . &#039;/&#039; ) );
&nbsp;
/** @since 1.5.0 */
!defined(&#039;SITECOOKIEPATH&#039;) &amp;&amp; define(&#039;SITECOOKIEPATH&#039;, preg_replace(&#039;|https?://[^/]+|i&#039;, &#039;&#039;, WP_SITEURL . &#039;/&#039; ) );
&nbsp;
/** @since 2.6.0 */
!defined(&#039;ADMIN_COOKIE_PATH&#039;) &amp;&amp; define( &#039;ADMIN_COOKIE_PATH&#039;, SITECOOKIEPATH . &#039;wp-admin&#039; );
&nbsp;
/** @since 2.6.0 */
!defined(&#039;PLUGINS_COOKIE_PATH&#039;) &amp;&amp; define( &#039;PLUGINS_COOKIE_PATH&#039;, preg_replace(&#039;|https?://[^/]+|i&#039;, &#039;&#039;, WP_PLUGIN_URL)  );
&nbsp;
/** @since 2.0.0 */
!defined(&#039;COOKIE_DOMAIN&#039;) &amp;&amp; define(&#039;COOKIE_DOMAIN&#039;, $_SERVER[&#039;SERVER_NAME&#039;]);</pre>
<hr class="C" />
<pre>/**
  * The WP_CACHE setting, if true, includes the wp-content/advanced-cache.php script, when executing wp-settings.php.
  * For an advanced caching plugin to use, static because you would only want one
  * if ( defined(&#039;WP_CACHE&#039;) )@include WP_CONTENT_DIR . &#039;/advanced-cache.php&#039;;
  */
!defined(&#039;WP_CACHE&#039;) &amp;&amp; define(&#039;WP_CACHE&#039;, true);
&nbsp;
/** WordPress Localized Language, defaults to en_US.
 *
 * Change this to localize WordPress.  A corresponding MO file for the chosen
 * language must be installed to wp-content/languages. For example, install
 * de.mo to wp-content/languages and set WPLANG to &#039;de&#039; to enable German
 * language support. */
!defined(&#039;WPLANG&#039;) &amp;&amp; define (&#039;WPLANG&#039;, &#039;en_US&#039;);
&nbsp;
/** Stores the location of the language directory. First looks for language folder in WP_CONTENT_DIR
 *   and uses that folder if it exists. Or it uses the "languages" folder in WPINC. @since 2.1.0 */
//!defined(&#039;WP_LANG_DIR&#039;) &amp;&amp; define(&#039;WP_LANG_DIR&#039;, ABSPATH . WPINC . &#039;/languages&#039;);
&nbsp;
/** LANGDIR defines what directory the WPLANG .mo file resides. If LANGDIR is not defined WordPress looks first to wp-content/languages and then wp-includes/languages for the .mo defined by WPLANG file.  Old static relative path maintained for limited backwards compatibility - won&#039;t work in some cases*/
//!defined(&#039;LANGDIR&#039;) &amp;&amp; define(&#039;LANGDIR&#039;, &#039;wp-content/languages&#039;);
&nbsp;
/** Stores the location of the WordPress directory of functions, classes, and core content. @since 1.0.0 */
//!defined(&#039;WPINC&#039;) &amp;&amp; define(&#039;WPINC&#039;, &#039;wp-includes&#039;);</pre>
<hr class="C" />
<h2>WPMU Stuff</h2>
<p>I personally don't use.</p>
<pre>/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined(&#039;WPMU_PLUGIN_DIR&#039;) &amp;&amp; define( &#039;WPMU_PLUGIN_DIR&#039;, WP_CONTENT_DIR . &#039;/mu-plugins&#039; ); // full path, no trailing slash
&nbsp;
/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined(&#039;WPMU_PLUGIN_URL&#039;) &amp;&amp; define( &#039;WPMU_PLUGIN_URL&#039;, WP_CONTENT_URL . &#039;/mu-plugins&#039; ); // full url, no trailing slash
&nbsp;
/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined( &#039;MUPLUGINDIR&#039; ) &amp;&amp; define( &#039;MUPLUGINDIR&#039;, &#039;wp-content/mu-plugins&#039; ); // Relative to ABSPATH.  For back compat.</pre>
<hr class="C" />
<h2>WordPress Database</h2>
<p>This is usually the only thing I have to manually edit when creating a new site, unless I just use the same DB and modify the $table_prefix, (farther down). I run everything I possibly can in UTF-8, but if you don't already know alot about character sets, wow it is one of the most confusing things so you may want to save learning about that topic for another day.  Otherwise the following are helpful (<em>and show how confusing character sets are!</em>)</p>
<ul>
    <li><a href="http://dev.mysql.com/doc/refman/5.0/en/charset-charsets.html">Character Sets and Collations MySQL Support</a></li>
    <li><a href="http://codex.wordpress.org/Converting_Database_Character_Sets">Converting Database Character Sets</a></li>
    <li><a href="http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html">UTF-8 character sets</a> (<a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a>)</li>
</ul>
<p>If you ever setup WP to use the builtin membership features, make sure you learn about the <code>CUSTOM_USER_TABLE</code> and <code>CUSTOM_USER_META_TABLE</code> constants, I've found them very helpful.</p>
<pre>/**#@+
 * MySQL settings
 */
/** The name of the database for WordPress */
define(&#039;DB_NAME&#039;, &#039;askapachewpblog75&#039;);
&nbsp;
/** The username to access the database */
define(&#039;DB_USER&#039;, &#039;askapache245d&#039;);
&nbsp;
/** The password for the username to access the database */
define(&#039;DB_PASSWORD&#039;, &#039;asdfklj2340&#039;);
&nbsp;
/** The hostname to connect to the database at */
define(&#039;DB_HOST&#039;, &#039;mysql.askapache.com&#039;);
&nbsp;
/** The charset of the database */
define(&#039;DB_CHARSET&#039;, &#039;utf8&#039;);
&nbsp;
/** The collation of the database */
define(&#039;DB_COLLATE&#039;, &#039;utf8_general_ci&#039;);</pre>
<hr class="C" />
<h2>$table_prefix</h2>
<p>The <code>$table_prefix</code> is the value placed in the front of your database tables. Change the value if you want to use something other than wp_ for your database prefix. Typically this is changed if you are <a href="http://codex.wordpress.org/Installing_Multiple_Blogs">installing multiple WordPress blogs</a> in the same database, and also for enhanced security.</p>
<p>Its a safe and good idea to change this value pre-installation to add more security to your WordPress blog. Exploits attempted against your WordPress blog by malicious crackers often are built with the premise that your blog uses the prefix wp_, by changing the value you mitigate some attack vectors. </p>
<pre>/**
 * WordPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
 */
$table_prefix  = &#039;ar15_&#039;;
&nbsp;
/** CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE are used to designated that the user and usermeta tables normally utilized by WordPress are not used, instead these values/tables are used to store your user information. */
//!defined(&#039;CUSTOM_USER_TABLE&#039;) &amp;&amp; define(&#039;CUSTOM_USER_TABLE&#039;, $table_prefix . &#039;my_users&#039;);
//!defined(&#039;CUSTOM_USER_META_TABLE&#039;) &amp;&amp; define(&#039;CUSTOM_USER_META_TABLE&#039;, $table_prefix . &#039;my_usermeta&#039;);</pre>
<h2>Setup PHP Ini Settings</h2>
<pre>
/** Turns the output of errors on or off, you really never want this on, you should only view errors by reading the log file. */
ini_set(&#039;display_errors&#039;, WP_DEBUG_DISPLAY);
&nbsp;
/** Tells whether script error messages should be logged to the server&#039;s error log or error_log. */
ini_set(&#039;log_errors&#039;, &#039;On&#039;);
&nbsp;
/** http://us.php.net/manual/en/timezones.php */
ini_set(&#039;date.timezone&#039;, &#039;America/Indianapolis&#039;);
&nbsp;
/** Where to log php errors */
ini_set(&#039;error_log&#039;, ASKAPACHE_ROOT . &#039;/logs/php_error.log&#039;);
&nbsp;
/** Set the memory limit, otherwise defaults to &#039;32M&#039; */
ini_set(&#039;memory_limit&#039;, WP_MEMORY_LIMIT);</pre>
<h2>Sessions are slow</h2>
<p>So I only use sessions when I have a specific use... In this case I need sessions only when one of the tools in the /online-tools/ directory is being used.  And that is for the <a href="http://www.askapache.com/security/php-captcha-anti-spam-example.html">captcha image</a>.  In the future I won't ever use sessions.</p>
<pre>if(preg_match( &#039;#^/online-tools/#&#039;,$_SERVER[&#039;REQUEST_URI&#039;])) session_start();</pre>
<h2>Include Custom Files</h2>
<p>Sure you could use the my-hacks.php that WP allows, or you can just stick your functions in your <code>TEMPLATEPATH/functions.php</code> file, but they are executed only after the wp-settings.php file, which may be too late for your file.</p>
<p>In the past I've also used the <a href="http://us2.php.net/manual/en/ini.core.php#ini.auto-prepend-file">auto_prepend_file</a> settings to run my script before anything (index.php) but I ran into some issues on different hosts, and it wasn't as portable.</p>
<p>This is useful because you can have a file with globally available functions that you can use in non-WP areas as well as WP areas.  I am moving away from this more and more as I learn more about classes and build plugins instead for portability.</p>
<pre>include_once ASKAPACHE_ROOT . &#039;/includes/myfunctions.inc&#039;;
&nbsp;
/** Sets up WordPress vars and included files. */
require_once(ABSPATH . &#039;wp-settings.php&#039;);
?&gt;</pre>
<h2>Some Useful PHP</h2>
<p>I am constantly trying to make my sites and code more portable, so I am using plugins alot more to accomplish things that I use to do with separate php.  Here are some examples of minimal php.</p>
<pre>add_filter("the_generator", create_function(&#039;$a&#039;,&#039;return "";&#039;));
add_filter(&#039;the_content&#039;, create_function(&#039;$a&#039;, &#039;return ((is_feed())? $a."&lt;p&gt;&lt;a href=\"".get_permalink()."\"&gt;".get_the_title()."&lt;/a&gt; originally appeared on ".get_bloginfo("name").".&lt;/p&gt;" : $a);&#039;), 99999);
add_filter(&#039;excerpt_length&#039;, create_function(&#039;$a&#039;, &#039;return 300;&#039;),99);
add_filter(&#039;excerpt_more&#039;, create_function(&#039;$a&#039;, &#039;return "&amp;hellip;";&#039;),99);
add_action( &#039;wp_head&#039;, create_function(&#039;$a&#039;,&#039;echo "&lt;link rel=\"pingback\" href=\"&#039;.get_bloginfo(&#039;pingback_url&#039;).&#039;\" /&gt;\n";&#039;), 95 );
add_action( &#039;wp_head&#039;, create_function(&#039;$a&#039;,&#039;echo "&lt;link rel=\"schema.rss\" href=\"http://purl.org/rss/1.0/\" /&gt;\n";&#039;), 96 );
add_action( &#039;wp_head&#039;, create_function(&#039;$a&#039;,&#039;echo "&lt;link rel=\"schema.rel\" href=\"http://purl.org/vocab/relationship/\" /&gt;\n";&#039;), 97 );
add_action( &#039;wp_head&#039;, create_function(&#039;$a&#039;,&#039;echo "&lt;link rel=\"meta\" type=\"application/rdf+xml\" href=\"/foaf.rdf\" /&gt;\n";&#039;), 98 );
add_action( &#039;wp_head&#039;, create_function(&#039;$a&#039;,&#039;echo "&lt;link href=\"/favicon.ico\" rel=\"shortcut icon\" type=\"image/x-icon\" /&gt;\n";&#039;), 99 );</pre>
<h2>Debugging Note</h2>
<p><a href="http://wordpress.org/extend/plugins/askapache-debug-viewer/screenshots/"><img alt="AskApache Advanced Debugging Output" src="http://s.wordpress.org/extend/plugins/askapache-debug-viewer/screenshot-1.png?r=160129" title="AskApache Advanced Debugging Output" width="625" height="548" /></a>If you read this far than you probably know how important debugging is, but I sometimes like to stick the best tips deep in my articles to make sure only YOU find it.  GRTFM isn't used on this site, it's mostly a requirement because my writing can get pretty bad..  The point, debugging is more than a crucial requirement if you want to do anything cool.  Don't worry I got you.. check my <a href="http://wordpress.org/extend/plugins/askapache-debug-viewer/">AskApache Debug Viewer Plugin from the official WP site</a>.  It's pretty close to providing as verbose amount of information that I could possibly figure out how to get out of php, probably more than you have ever seen at least, I focused on quantity.  I use it all the time on new installs as there is no setup required and it tells me advanced information about the setup of the server, hacker code for sure.<br class="C" />
</p>
<p>Here's a quick function to see set global vars, I just think this is interesting code.</p>
<pre>function askapache_global_debug(){
  global $_GET,$_POST,$_COOKIE,$_SESSION,$_ENV,$_FILES,$_SERVER,$_REQUEST,$HTTP_POST_FILES,$HTTP_POST_VARS,$HTTP_SERVER_VARS,$HTTP_RAW_POST_DATA,$HTTP_GET_VARS,$HTTP_COOKIE_VARS,$HTTP_ENV_VARS;
  $gv=create_function(&#039;$n&#039;,&#039;global $$n; ob_start(); if ( is_array($$n) &amp;&amp; sizeof($$n)&gt;0 &amp;&amp; print("[{$n}]\n") ) print_r($$n);return ob_get_clean();&#039;);
  foreach (array(&#039;_GET&#039;,&#039;_POST&#039;,&#039;_COOKIE&#039;,&#039;_SESSION&#039;,&#039;_ENV&#039;,&#039;_FILES&#039;,&#039;_SERVER&#039;,&#039;_REQUEST&#039;,&#039;HTTP_POST_FILES&#039;,&#039;HTTP_POST_VARS&#039;,&#039;HTTP_SERVER_VARS&#039;,&#039;HTTP_RAW_POST_DATA&#039;,&#039;HTTP_GET_VARS&#039;,&#039;HTTP_COOKIE_VARS&#039;,&#039;HTTP_ENV_VARS&#039;) as $k)echo $gv($k);
  print_r(get_defined_constants());
}</pre>
<p class="anote">Also check the WordPress Codex page: <a href="http://codex.wordpress.org/Editing_wp-config.php">Editing wp-config.php</a> and Perishable Press's: <a href="http://perishablepress.com/press/2009/12/01/stupid-wordpress-tricks/">Stupid WordPress Tricks</a></p><p><a href="http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html"></a><a href="http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html">Advanced WordPress wp-config.php Tweaks</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/wordpress/advanced-wp-config-php-tweaks.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Optimizing Servers and Processes for Speed with ionice, nice, ulimit</title>
		<link>http://www.askapache.com/optimize/optimize-nice-ionice.html</link>
		<comments>http://www.askapache.com/optimize/optimize-nice-ionice.html#comments</comments>
		<pubDate>Sat, 10 Oct 2009 05:41:28 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Optimization]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3167</guid>
		<description><![CDATA[<p><a href="http://www.askapache.com/linux/optimize-nice-ionice.html" class="IFL" id="id18"></a>To prepare for several upcoming articles on AskApache that are focused on optimizing Servers and Sites from a server admin level, here is an article to introduce the main tools that we will be using.  These tools are used to optimize CPU time for each process using <strong>nice</strong> and <strong>renice</strong>, and other tools like <strong>ionice</strong> are used to optimize the Disk IO, or Disk speed / Disk traffic for each process.  Then you can make sure your mysqld and httpd processes are always fast and prioritized.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/optimize/optimize-nice-ionice.html"></a><a href="http://www.askapache.com/optimize/optimize-nice-ionice.html"><cite>AskApache.com</cite></a></p><p>Ok, sup.  I really felt I had to get this out of the way, because I have a whole stack of drafts waiting to be published, but I realized that not many people will benefit from all the advanced optimizations and tricks I'm writing unless they get a basic understanding of some of the tools I'm using.  I decided to write a series of articles explaining how I optimize servers for speed because lately I've been getting a lot more people wanting to hire me to do that.  I take on projects when I can but there is clearly a need out here on the net for some self-help.   The momentum is swinging more and more towards VPS type of web hosting, and I would say that 99% of those customers are getting supremely ripped off, which goes against the foundation of the web.</p>
<p>Keep in mind that this blog and my research is only a hobby of mine, my job is primarily marketing and sales, so I'm not some licensed expert or anything, or even an unlicensed expert! haha.  But it does bother me that those who are tech-savvy enough to run web-hosting companies are happily ripping people off.  So this article details the main tools that are used to speed up and optimize your machine by delegating levels of priority to specific processes.  Future articles will use these tools alot, so this is meant as an intro.</p>




<p><a id="cpu-disk-io" name="cpu-disk-io"></a></p><h2>CPU and Disk I/O</h2>
<p>As most of you are aware, there are 2 variables that determine any computer or programs speed.  CPU and Disk I/O.  CPU determines how fast you can process data, crunch numbers, etc. while disk I/O determines how fast your disks can read and write data to the hard-drive.  Wouldn't it be great if you could easily configure your server to give your httpd, php, and other processes both greater CPU processing and disk IO than your non-important processes like backup scripts, ftp daemons, etc.?  We are talking about Linux in this article, so of course YES not only can you do that, you should!</p>
<p><a name="optimize-ram" id="optimize-ram"></a></p><h3>RAM</h3>
<p>RAM is like a hard-drive in that data is stored on it, and read/written to it.  The difference is that RAM is somewhere around 30x faster than disk I/O, but the cost of that incredible speed is that the data stored on it is only temporary in the sense that it won't be stored permanently, it is completely erased when your machine is rebooted.  RAM is also expensive, and there is a limit to how much a server or machine can have due to hardware limits.</p>
<p><a name="optimize-swap" id="optimize-swap"></a></p><h3>SWAP</h3>
<p>SWAP takes off when you run out of RAM but you still want certain data to be read/write quickly.  Basically when you start running out of RAM your machine starts supplementing RAM with SWAP storage.  SWAP is usually a partition on a second hard-drive disk.  There is an upper limit on how much I/O can occur on a disk at one time, and the more I/O takes place, the slower all I/O becomes, so SWAP works well on a separate hard-drive as it will have much faster I/O.  On Windows they opted to copy the SWAP mechanism but instead use a file named pagefile.sys, and that is just one reason people in the know do not care for Windows.</p>
<p><a name="optimize-cpu" id="optimize-cpu"></a></p><h3>CPU</h3>
<p>So lets do this, think of your CPU (your processor) as having an amount of 100% processing available when not being used, 0% when its maxed out.  CPU's handle multiple processing tasks simultaneously, so what we will discuss in this article is how to specify HOW MUCH of that processing amount each of your programs (heretofore "processes") are able to use.  Yes, very very cool.</p>
<p>That is correct, you can easily configure your server to provide more of the available processing time to certain programs over others, like you can configure apache and php to utilize 50% of your CPU processing time by themselves, so that all other processes (proftpd, sshd, rsync, etc.) combined can only utilize 50%.  The terminology is we can give certain specific processes (like php.cgi, httpd, fast-cgi.cgi) a specific <strong>priority</strong>, where -19 is the most priority, and +19 is the least amount of priority, or CPU processing time.  I know it seems backwards.. </p>


<p><a id="tools" name="tools"></a></p><h2>The Tools</h2>
<p>If you run Windows, you are in the right place... because the following advice will save your life:  GET LINUX! Ok, now that that is out of the way, the following are the tools dicussed on this page.  All of them are free, open-source, and wonderful.  The basic idea of these tools is to control how much CPU is devoted to each process, and also how much Disk IO/Disk traffic is given to each process.</p>
<dl>
<dt><a href="#nice-tool">nice</a></dt><dd>run a program with modified scheduling priority</dd>
<dt><a href="#renice-tool">renice</a></dt><dd>alter priority of running processes</dd>
<dt><a href="#ionice-tool">ionice</a></dt><dd>set or retrieve the I/O priority for a given pid or execute a new task with a given I/O priority.</dd>
<dt><a href="#iostat-tool">iostat</a></dt><dd>Report Central Processing Unit (CPU) statistics and input/output statistics for devices and partitions.</dd>
<dt><a href="#ulimit-tool">ulimit</a></dt><dd>Ulimit provides control over the resources available to processes started by the shell, on systems that allow such control.</dd>
<dt><a href="#chrt-tool">chrt</a></dt><dd>set or retrieve real-time scheduling parameters for a given pid or execute a new task under given scheduling parameters.</dd>
<dt><a href="#taskset-tool">taskset</a></dt><dd>set or retrieve task CPU affinity for a given pid or execute a new task under a given affinity mask.</dd>
<dt></dt><dd></dd>
</dl>




<p><a id="part1-processes" name="part1-processes"></a></p><h2>Part 1: Process Processes Faster</h2>
<p>Ok so lets tackle figuring out how to give your response-intensive processes (like apache, php, ruby, perl, java) meaning a request to your server/machine requires a <em>response</em>.  For instance, when you requested this page that you are reading at this very second, several things on my server had to happen for you to be able to read this.</p>
<p>First your computer sends out a request to see what server the www.askapache.com domain name is.  DNS servers respond with my server IP, so for servers dedicated as nameservers, optimizing the DNS processes like bind would speed that up.  Now that your computer knows how to reach my server it sends an HTTP GET request for this url.  This request is received by the httpd process that is apache, and apache determines this url should be handled by my custom compiled php5.3.0 binary, because this page is WordPress generated.  So the php binary loads up the WordPress /index.php file, which chain-loads several other php files, including <code>wp-config.php</code> containing my MySql database settings.  Now php connects to my MySql Server to fetch this articles content, comments, title, tags, etc. and then generates the HTML and hands that back to Apache.</p>
<p>Finally, Apache generates a HTTP RESPONSE and sends the RESPONSE and CONTENT back to your Browser, which then in turn renders the page for your eyes with the necessary javascript, images, css, and other files included in the HTML response.</p>

<h3>Too much Processing</h3>
<p>Now you see why I've opted to write my own caching plugin that takes the php and mysql processes OUT of that equation.  Both the php binary and the mysql instance consume CPU processing, and disk IO, to load all their library files, make various network requests and sockets, check permissions, and on and on.  And that's completely ok, the thing is, unless you configure these processes (Apache, PHP, MySQL) they will use the same amount of CPU processing that other processes use, other processes that have very little to do with you reading this sentence.  Processes to run my mail server, my FTP server, my SSH server, my cronjobs, cleanup scripts, atd daemon, etc.. and they will get the same amount of CPU!</p>
<p>Another even simpler example is what got me to look into this myself.  I wrote a shell script that created hourly, daily, weekly, and monthly backups for all of my websites and sql databases, and set it up to run by cronjob at those set intervals.  Eventually I noticed my sites were slower, my php even slower, and sometimes I even saw 503 errors that my host throws up when my server is overloaded.  The research that I pursued to prevent that from happening has been hugely eye-opening.  What does a backup script do?  Mine just created tar archives of all the files in my web root, then gzipped the tar archive saving to a backup server using scp (a file transfer using ssh).  This resulted in the following huge problems that seem to have nothing to do with a faster server and speedier website, but they have everything to with it.</p>
<ol>
<li><strong>CPU Bottleneck #1</strong> - tar and gzip use compression algorithms at a low level to create a compressed version, and all that compressing uses a whole lot of crunching - CPU processing</li>
<li><strong>DISK IO Bottleneck</strong> - Tarring the whole web root directory was creating a ton of disk io, and remember the more disk io that is going on, the less is available for everything else.</li>
<li><strong>CPU Bottleneck #2</strong> - Using scp to send my backups was security-smart, but these huge archive files had to be encrypted and sent over the net.</li>
</ol>






<p><a id="breaking-bottlenecks" name="breaking-bottlenecks"></a></p><h2>Breaking Bottles</h2>
<p>I apologize for being a little long-winded there, but I think it's important to make sure everyone understands those basic concepts, which are foreign to most people.  Once you understand what is causing the bottlenecks, then you can understand the solutions, which actually are incredibly simple and even a novice linux user can easily do.  Besides, the net gets a little bit faster every time someone implements this.</p>

<p><a id="nice-tool" name="nice-tool"></a></p><h3>nice</h3>
<p><img src="http://uploads.askapache.com/2009/10/nice-chart.png" alt="NICE Levels Chart" title="NICE Levels Chart" width="351" height="225" class="IFL" />Nice allows you to run a program with modified scheduling priority which specifies how much CPU is devoted to a particular process.  Run COMMAND with an adjusted niceness, which affects process scheduling.  With no COMMAND, print the current niceness.  <br /><br />Nicenesses range from -20 (most favorable scheduling) to 19 (least favorable).   <code>-n, --adjustment=N</code> -  add integer N to the niceness (default 10).   <code>nice +19</code> tasks get a HZ-independent 1.5%.  Running a <code>nice +10</code> and a <code>nice +11</code> task means the first will get 55% of the CPU, the other 45%.<br class="C" /></p>

<p><a id="nice-usage" name="nice-usage"></a></p><h4>nice usage</h4>
<pre>nice [OPTION] [COMMAND [ARG]...]
&nbsp;
-n, --adjustment=ADJUST   increment priority by ADJUST first</pre>

<p><a id="nice-examples" name="nice-examples"></a></p><h4>Examples of nice</h4>
<p>Using nice to download a file</p>
<pre>nice -n 17 curl -q -v -A &#039;Mozilla/5.0&#039; -L -O http://wordpress.org/latest.zip</pre>
<p>Unzipping a file with nice</p>
<pre>nice -n 17 unzip latest.zip</pre>
<p>Nice way to build from source</p>
<pre>nice -n 2 ./configure
nice -n 2 make
nice -n 2 make install</pre>
<p>It is sometimes useful to run non-interactive programs with reduced priority.</p>
<pre>$ nice factor `echo &#039;2^9 - 1&#039;|bc`
511: 7 73</pre>
<p>Since nice prints the current priority, we can invoke it through itself to demonstrate how it works: The default behavior is to reduce priority by 10.</p>
<pre> $ nice nice
10
$ nice -n 10 nice
10</pre>
<p> The ADJUSTMENT is relative to the current priority.  The first <code>nice</code> invocation runs the second one at priority 10, and it in turn runs the final one at a priority lowered by 3 more.</p>
<pre>$ nice nice -n 3 nice
13</pre>
<p>Specifying a priority larger than 19 is the same as specifying 19.</p>
<pre>$ nice -n 30 nice
19</pre>
<p>Only a privileged user may run a process with higher priority.</p>
<pre>$ nice -n -1 nice
nice: cannot set priority: Permission denied
$ sudo nice -n -1 nice
-1</pre>

<blockquote cite="http://uploads.askapache.com/2009/08/sched-nice-design.txt">
<p>The new scheduler in v2.6.23 addresses all three types of complaints:</p>
<p>To address the first complaint (of nice levels being not "punchy" enough), the scheduler was decoupled from 'time slice' and HZ concepts (and granularity was made a separate concept from nice levels) and thus it was possible to implement better and more consistent nice +19 support: with the new scheduler nice +19 tasks get a HZ-independent 1.5%, instead of the variable 3%-5%-9% range they got in the old scheduler.</p>
<p>To address the second complaint (of nice levels not being consistent), the new scheduler makes nice(1) have the same CPU utilization effect on tasks, regardless of their absolute nice levels. So on the new scheduler, running a nice +10 and a nice 11 task has the same CPU utilization "split" between them as running a nice -5 and a nice -4 task. (one will get 55% of the CPU, the other 45%.) That is why nice levels were changed to be "multiplicative" (or exponential) - that way it does not matter which nice level you start out from, the 'relative result' will always be the same.</p>
<p>The third complaint (of negative nice levels not being "punchy" enough and forcing audio apps to run under the more dangerous SCHED_FIFO scheduling policy) is addressed by the new scheduler almost automatically: stronger negative nice levels are an automatic side-effect of the recalibrated dynamic range of nice levels.</p>
</blockquote>







<p><a id="renice-tool" name="renice-tool"></a></p><h3>renice</h3>
<p>Renice is similar to the nice command, but it lets you modify the nice of a currently running process.  This is nice for shell scripts where you can add this to the top of the script to nicify the whole script to 19.</p>

<p><a id="renice-usage" name="renice-usage"></a></p><h4>renice usage</h4>
<pre>renice priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ]
&nbsp;
-g      Force who parameters to be interpreted as process group ID&#039;s.
-u      Force the who parameters to be interpreted as user names.
-p      Resets the who interpretation to be (the default) process ID&#039;s.</pre>

<p><a id="renice-examples" name="renice-examples"></a></p><h4>Examples of renice</h4>
<p>From the shell, changes the priority of the shell and all children to 19.  From a shell script, does the same but only for the script and its children.</p>
<pre>renice 19 -p $$</pre>
<p>This runs renice without any output</p>
<pre>renice 19 -p $$ &amp;&gt;/dev/null</pre>
<p>10 gets more CPU than 19</p>
<pre>renice 10 -p $$</pre>
<p>change the priority of process ID's 987 and 32, and all processes owned by users daemon and root.</p>
<pre>renice +1 987 -u daemon root -p 32</pre>









<p><a id="part2-disk-io" name="part2-disk-io"></a></p><h2>Part 2: Optimizing Disk I/O</h2>
<p><a id="scheduling-policies" name="scheduling-policies"></a></p><h3>Linux Scheduling Policies</h3>
<p>The scheduler is the kernel component that decides which runnable process will be executed by the CPU next.  Each process has an associated scheduling policy and a static scheduling priority, sched_priority</p>
<p>Processes scheduled under one of the real-time policies (SCHED_FIFO, SCHED_RR) have a sched_priority value in the <strong>range 1 (low) to 99 (high)</strong>.  (As the numbers imply, real-time processes always have higher priority than normal processes.)   The following "real-time" policies are also supported, for special time-critical applications that need precise control over the way in which runnable processes are selected for execution:</p>
<p>Currently, Linux supports the following "normal" (i.e., non-real-time) scheduling policies:</p>
<dl>
<dt><strong>SCHED_OTHER</strong>: Default Linux time-sharing scheduling</dt><dd>The standard round-robin time-sharing policy</dd><dt><strong>SCHED_BATCH</strong>: Scheduling batch processes</dt><dd>This policy is useful for workloads that are non-interactive, but do not want to lower their nice value, and for workloads that want a deterministic scheduling policy without interactivity causing extra preemptions (between the workload's tasks).</dd>
<dt><strong>SCHED_IDLE</strong>: Scheduling very low priority jobs</dt>
<dd>This policy is intended for running jobs at extremely low priority (lower even than a +19 nice value with the SCHED_OTHER or SCHED_BATCH policies)</dd>
<dt><strong>SCHED_FIFO</strong>: First In-First Out scheduling</dt><dd>A first-in, first-out policy</dd>
<dt><strong>SCHED_RR</strong>: Round Robin scheduling</dt><dd>A round-robin policy.</dd>
</dl>

<p><a id="scheduling-classes" name="scheduling-classes"></a></p><h3>Scheduling Classes</h3>
<dl>
<dt><code>IOPRIO_CLASS_RT</code></dt>
<dd>This is the realtime io class. The RT scheduling class is given first access to the disk, regardless of what else is going on in the system. Thus the RT class needs to be used with some care, as it can starve other processes. As with the best effort class, 8 priority levels are defined denoting how big a time slice a given process will receive on each scheduling window.  This scheduling class is given higher priority than any other in the system, processes from this class are given first access to the disk every time. Thus it needs to be used with some care, one io RT process can starve the entire system. Within the RT class, there are 8 levels of class data that determine exactly how much time this process needs the disk for on each service. In the future this might change to be more directly mappable to performance, by passing in a wanted data rate instead.</dd>
<dt><code>IOPRIO_CLASS_BE</code></dt>
<dd>This is the best-effort scheduling class, which is the default for any process that hasn't set a specific io priority. This is the default scheduling class for any process that hasn't asked for a specific io priority. Programs inherit the CPU nice setting for io priorities. This class takes a priority argument from 0-7, with lower number being higher priority. Programs running at the same best effort priority are served in a round-robin fashion.  The class data determines how much io bandwidth the process will get, it's directly mappable to the cpu nice levels just more coarsely implemented. 0 is the highest BE prio level, 7 is the lowest. The mapping between cpu nice level and io nice level is determined as: io_nice = (cpu_nice + 20) / 5.</dd>
<dt><code>IOPRIO_CLASS_IDLE</code></dt>
<dd>This is the idle scheduling class, processes running at this level only get io time when no one else needs the disk. A program running with idle io priority will only get disk time when no other program has asked for disk io for a defined grace period. The impact of idle io processes on normal system activity should be zero. This scheduling class does not take a priority argument.    The idle class has no class data, since it doesn't really apply here.</dd>
</dl>








<p><a id="ionice-tool" name="ionice-tool"></a></p><h3>ionice</h3>
<p>ionice - get/set program io scheduling class and priority.  This program sets the io scheduling class and priority for a program.  Since v3 (aka CFQ Time Sliced) CFQ implements I/O nice levels similar to those of CPU scheduling. These nice levels are grouped in three scheduling classes each one containing one or more priority levels:</p>

<p><a id="ionice-usage" name="ionice-usage"></a></p><h4>ionice usage</h4>
<p>If no arguments or just -p is given, ionice will query the current io scheduling class and priority for that process.</p>
<pre>ionice [-c] [-n] [-p] [COMMAND [ARG...]]</pre>
<ul>
<li><strong>-c</strong> - The scheduling class. 1 for real time, 2 for best-effort, 3 for idle.</li>
<li><strong>-n</strong> - The scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data.</li>
<li><strong>-p</strong> - Pass in a process pid to change an already running process. If this argument is not given, ionice will run the listed program with the given parameters.</li>
</ul>

<p><a id="ionice-examples" name="ionice-examples"></a></p><h4>ionice Examples</h4>
<p>Sets process with PID 89 as an idle io process.</p>
<pre>ionice -c3 -p89</pre>
<p>Runs 'bash' as a best-effort program with highest priority.</p>
<pre>ionice -c2 -n0 bash</pre>
<p>Returns the class and priority of the process with PID 89</p>
<pre>ionice -p89</pre>

<blockquote cite="http://gaarai.com/2009/03/06/multitasking-from-the-linux-command-line-plus-process-prioritization/">
<p><p>With the ionice command, you can set the IO priority for a process to one of three classes: Idle (3), Best Effort (2), and Real Time (1). The Idle class means that the process will only be able to read and write to the disk when all other processes are not using the disk. The Best Effort class is the default and has eight different priority levels from 0 (top priority) to 7 (lowest priority). The Real Time class results in the process having first access to the disk irregardless of other process and should never be used unless you know what you are doing.</p>
<p>If we wish to run the updatedb process in the background with an Idle IO class priority, we can run the following:</p>
<pre>$ sudo date
$ sudo updatedb &amp;
[1] 16324
$ sudo ionice -c3 -p16324</pre>
<p>If we’d rather just lower the Best Effort class priority (defaults to 4) for the command so the process isn’t limited to idle IO periods, we can run the following:</p>
<pre>$ sudo date
$ sudo updatedb &amp;
[1] 16324
$ sudo ionice -c2 -n7 -p16324</pre>
<p>Again, the Real Time class should not be used as it can prevent you from being able to interact with your system.</p>
<p>You may wonder where you can get the process ID if you don’t know it, can’t remember it, or didn’t start the process (an automatted script may have launched it). You can find process IDs with the ps command.</p>
<p>For example, if I had an updatedb program running in the background, and I wanted to find its process ID, I can run the following:</p>
<pre>$ ps -C updatedb
PID TTY TIME CMD
4234 ? 00:00:42 updatedb</pre>
<p>This tells me that the process’ process ID (PID) is 4234.</p></p>
</blockquote>





<p><a id="iostat-tool" name="iostat-tool"></a></p><h3>iostat</h3>
<p><a id="iostat-usage" name="iostat-usage"></a></p><h4>iostat Usage</h4>
<pre>iostat [ -c ] [ -d ] [ -N ] [ -n ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ] [ &lt;device&gt; [...] | ALL ] [ -p [ &lt;device&gt; [,...] | ALL ] ] [ &lt;interval&gt; [ &lt;count&gt; ] ]
&nbsp;
-c     The -c option is exclusive of the -d option and displays only the CPU usage report.
-d     The -d option is exclusive of the -c option and displays only the device utilization report.
-k     Display statistics in kilobytes per second instead of blocks per second.  Data displayed are valid only with kernels 2.4 and newer.
-m     Display statistics in megabytes per second instead of blocks or kilobytes per second.  Data displayed are valid only with kernels 2.4 and newer.
-n     Displays the NFS-directory statistic.  Data displayed are valid only with kernels 2.6.17 and newer.  This option is exclusive ot the -x option.
-h     Display the NFS report more human readable.
-p [ { device | ALL } ]   The  -p  option  is  exclusive  of  the -x option and displays statistics for block devices and all their partitions that are used by the system.
-t     Print the time for each report displayed.
-x     Display extended statistics.</pre>

<p><a id="iostat-examples" name="iostat-examples"></a></p><h4>iostat Examples</h4>
<pre>iostat -p ALL 2 1000
avg-cpu:  %user   %nice    %sys %iowait   %idle
            8.34    0.08    1.26    2.27   88.05</pre>
<p>Display a single history since boot report for all CPU and Devices.</p>
<pre>$ iostat</pre>
<p>Display a continuous device report at two second intervals.</p>
<pre>$ iostat -d 2</pre>
<p>Display six reports at two second intervals for all devices.</p>
<pre>$ iostat -d 2 6</pre>
<p>Display six reports of extended statistics at two second intervals for devices hda and hdb.</p>
<pre>$ iostat -x hda hdb 2 6</pre>
<p>Display six reports at two second intervals for device sda and all its partitions (sda1, etc.)</p>
<pre>$ iostat -p sda 2 6</pre>






<p><a id="schedule-utils" name="schedule-utils"></a></p><h2>Schedule Utils</h2>
<p>These are the Linux scheduler utilities - schedutils for short.  These programs take advantage of the scheduler family of syscalls that Linux implements across various kernels.  These system calls implement interfaces for scheduler-related parameters such as CPU affinity and real-time attributes.  The standard UNIX utilities do not provide support for these interfaces -- thus this package.</p>
<p>The programs that are included in this package are chrt and taskset.  Together with nice and renice (not included), they allow full control of process scheduling parameters.  Suggestions for related utilities are welcome, although it is believed (barring new interfaces) that all scheduling interfaces are covered.</p>
<p>I've found that quite a few servers do not have this package installed, indicating to you that they might not know what they are doing.  Here is how you can install this incredible package, for non-root users.  Root users know how to do this, or they shouldn't be root.  Download and install in 1 line provided you have curl.  Or just use the following commands.</p>
<pre>mkdir -pv $HOME/{dist,source,bin,share/man/man1} &amp;&amp; cd ~/dist &amp;&amp; curl -O http://ftp.de.debian.org/debian/pool/main/s/schedutils/schedutils_1.5.0.orig.tar.gz &amp;&amp; cd ~/source &amp;&amp; tar -xvzf ~/dist/sch*z &amp;&amp; cd sch* &amp;&amp; sed -i -e &#039;s,= /usr/local,=${HOME},g&#039; Makefile &amp;&amp; make &amp;&amp; make install &amp;&amp; make installdoc</pre>
<pre>mkdir -pv $HOME/{dist,source,bin,share/man/man1}
cd ~/dist &amp;&amp; curl -O http://ftp.de.debian.org/debian/pool/main/s/schedutils/schedutils_1.5.0.orig.tar.gz
cd ~/source &amp;&amp; tar -xvzf ~/dist/schedutils_1.5.0.orig.tar.gz
cd ~/source/schedutils-1.5.0 &amp;&amp; sed -i -e &#039;s,= /usr/local,=${HOME},g&#039; Makefile
make || make -d &amp;&amp; make install || make install -d &amp;&amp; make installdoc || make installdoc -d</pre>


<p><a id="taskset-tool" name="taskset-tool"></a></p><h3>taskset</h3>
<p>Taskset  is  used to set or retrieve the CPU affinity of a running process given its PID or to launch a new COMMAND with a given CPU affinity.  CPU affinity is a scheduler property that "bonds" a process to a given set of CPUs on the system.  The Linux scheduler will honor the given CPU affinity and the process will not run on any other CPUs.  Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practical for performance reasons.  Therefore, forcing a specific CPU affinity is useful only in certain applications.</p>
<p>The  CPU  affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corresponding to the last logical CPU.  Not all CPUs may exist on a given system but a mask may specify more CPUs than are present.  A retrieved mask will reflect only the bits that correspond to CPUs physically on the system.  If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned.  A user must possess CAP_SYS_NICE to change the CPU affinity of a process.  Any user can retrieve the affinity mask.</p>

<p><a id="taskset-usage" name="taskset-usage"></a></p><h4>taskset Usage</h4>
<pre>taskset [options] [mask | cpu-list] [pid | cmd [args...]]
&nbsp;
-p, --pid            operate on existing given pid
-c, --cpu-list     display and specify cpus in list format</pre>

<p><a id="taskset-examples" name="taskset-examples"></a></p><h4>taskset-examples</h4>
<p>The default behavior is to run a new command:</p>
 <pre>$ taskset 03 sshd -b 1024</pre>
<p>You can retrieve the mask of an existing task or set it:</p>
<pre>$ taskset -p 700
$ taskset -p 03 700</pre>
<p>List format uses a comma-separated list instead of a mask:</p>
<pre>$ taskset -pc 0,3,7-11 700</pre>




<p><a id="chrt-tool" name="chrt-tool"></a></p><h3>chrt</h3>
<p><code>chrt</code> sets or retrieves the real-time scheduling attributes of an existing PID or runs COMMAND with the given attributes.  Both policy (one of <code>SCHED_FIFO</code>, <code>SCHED_RR</code>, or <code>SCHED_OTHER</code>) and priority can be set and retrieved.  A user must possess CAP_SYS_NICE to change the scheduling attributes of a process.  Any user can retrieve the scheduling information.</p>

<p><a id="chrt-usage" name="chrt-usage"></a></p><h4>chrt Usage</h4>
<pre>chrt [options] [prio] [pid | cmd [args...]]
&nbsp;
-p, --pid operate on an existing PID and do not launch a new task
-f, --fifo set scheduling policy to SCHED_FIFO
-m, --max show minimum and maximum valid priorities, then exit
-o, --other set policy scheduling policy to SCHED_OTHER
-r, --rr set scheduling policy to SCHED_RR (the default)</pre>

<p><a id="chrt-examples" name="chrt-examples"></a></p><h4>chrt Examples</h4>
<p>The default behavior is to run a new command:   <code>chrt [prio] -- [command] [arguments]</code></p>
<p>You can also retrieve the real-time attributes of an existing task:</p>
<pre>chrt -p [pid]</pre>
<p>Or set them:</p>
<pre>chrt -p [prio] [pid]</pre>













<p><a id="ulimit-tool" name="ulimit-tool"></a></p><h2>ulimit - get and set user limits</h2>
<p>Ulimit provides control over the resources available to processes started by the shell, on systems that allow such control. One can set the resource limits of the shell using the built-in ulimit command.  The shell's resource limits are inherited by the processes that it creates to execute commands.</p>

<p><a id="ulimit-usage" name="ulimit-usage"></a></p><h4>ulimit Usage</h4>
<pre>ulimit [-SHacdfilmnpqstuvx] [limit]</pre>
<dl>
<dt>-S</dt><dd>use the `soft' resource limit</dd>
<dt>-H</dt><dd>use the `hard' resource limit</dd>
<dt>-a</dt><dd>all current limits are reported</dd>
<dt>-c</dt><dd>the maximum size of core files created</dd>
<dt>-d</dt><dd>the maximum size of a process's data segment</dd>
<dt>-f</dt><dd>the maximum size of files created by the shell</dd>
<dt>-l</dt><dd>the maximum size a process may lock into memory</dd>
<dt>-m</dt><dd>the maximum resident set size</dd>
<dt>-n</dt><dd>the maximum number of open file descriptors</dd>
<dt>-p</dt><dd>the pipe buffer size</dd>
<dt>-s</dt><dd>the maximum stack size</dd>
<dt>-t</dt><dd>the maximum amount of cpu time in seconds</dd>
<dt>-u</dt><dd>the maximum number of user processes</dd>
<dt>-v</dt><dd>the size of virtual memory</dd>
</dl>
<p>If LIMIT is given, it is the new value of the specified resource; the special LIMIT values `soft', `hard', and `unlimited' stand for the current soft limit, the current hard limit, and no limit, respectively.  Otherwise, the current value of the specified resource is printed.  If no option is given, then -f is assumed.  Values are in 1024-byte increments, except for -t, which is in seconds, -p, which is in increments of 512 bytes, and -u, which is an unscaled number of processes.</p>
<dl>
<dt>RLIMIT_AS</dt>
<dd>The maximum size of the process's virtual memory (address space) in bytes.  This limit affects calls to brk(2), mmap(2) and mremap(2), which fail with the error ENOMEM upon exceeding this limit.  Also automatic stack expansion will fail (and generate a SIGSEGV that kills the process if no alternate stack has been made available via sigaltstack(2)).  Since the value is a long, on machines with a 32-bit long either this limit is at most 2 GiB, or this resource is unlimited.</dd>
<dt>RLIMIT_CORE</dt>
<dd>Maximum size of core file.  When 0 no core dump files are created. When non-zero, larger dumps are truncated to this size.</dd>
<dt>RLIMIT_CPU CPU</dt>
<dd>time limit in seconds.  When the process reaches the soft limit, it is sent a SIGXCPU signal.  The default action for this signal is to terminate the process.  However, the signal can be caught, and the handler can return control to the main program.  If the process continues to consume CPU time, it will be sent SIGXCPU once per second until the hard limit is reached, at which time it is sent SIGKILL. (This latter point describes Linux 2.2 through 2.6 behavior. Implementations vary in how they treat processes which continue to consume CPU time after reaching the soft limit.  Portable applications that need to catch this signal should perform an orderly termination upon first receipt of SIGXCPU.)</dd>
<dt>RLIMIT_DATA</dt>
<dd>The maximum size of the process's data segment (initialized data, uninitialized data, and heap).  This limit affects calls to brk(2) and sbrk(2), which fail with the error ENOMEM upon encountering the soft limit of this resource.</dd>
<dt>RLIMIT_FSIZE</dt>
<dd>The maximum size of files that the process may create.  Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. By default, this signal terminates a process, but a process can catch this signal instead, in which case the relevant system call (e.g., write(2), truncate(2)) fails with the error EFBIG.</dd>
<dt>RLIMIT_LOCKS</dt>
<dd>(Early Linux 2.4 only) A limit on the combined number of flock(2) locks and fcntl(2) leases that this process may establish.</dd>
<dt>RLIMIT_MEMLOCK</dt>
<dd>The maximum number of bytes of memory that may be locked into RAM.  In effect this limit is rounded down to the nearest multiple of the system page size.  This limit affects mlock(2) and mlockall(2) and the mmap(2) MAP_LOCKED operation.  Since Linux 2.6.9 it also affects the shmctl(2) SHM_LOCK operation, where it sets a maximum on the total bytes in shared memory segments (see shmget(2)) that may be locked by the real user ID of the calling process.  The shmctl(2) SHM_LOCK locks are accounted for separately from the per-process memory locks established by mlock(2), mlockall(2), and mmap(2) MAP_LOCKED; a process can lock bytes up to this limit in each of these two categories.  In Linux kernels before 2.6.9, this limit controlled the amount of memory that could be locked by a privileged process.  Since Linux 2.6.9, no limits are placed on the amount of memory that a privileged process may lock, and this limit instead governs the amount of memory that an unprivileged process may lock.</dd>
<dt>RLIMIT_MSGQUEUE</dt>
<dd>(Since Linux 2.6.8) Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process.  This limit is enforced for mq_open(3).  Each message queue that the user creates counts (until it is removed) against this limit according to the formula:  <code>bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +             attr.mq_maxmsg * attr.mq_msgsize</code> where attr is the mq_attr structure specified as the fourth argument to mq_open(3).  The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead).</dd>
<dt>RLIMIT_NICE</dt>
<dd>(since Linux 2.6.12, but see BUGS below) Specifies a ceiling to which the process's nice value can be raised using setpriority(2) or nice(2).  The actual ceiling for the nice value is calculated as 20 - rlim_cur.  (This strangeness occurs because negative numbers cannot be specified as resource limit values, since they typically have special meanings.  For example, RLIM_INFINITY typically is the same as -1.)</dd>
<dt>RLIMIT_NOFILE</dt>
<dd>Specifies a value one greater than the maximum file descriptor number that can be opened by this process.  Attempts (open(2), pipe(2), dup(2), etc.)  to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.)</dd>
<dt>RLIMIT_NPROC</dt>
<dd>The maximum number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of the calling process.  Upon encountering this limit, fork(2) fails with the error EAGAIN.</dd>
<dt>RLIMIT_RSS</dt>
<dd>Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM).  This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.</dd>
<dt>RLIMIT_RTPRIO</dt>
<dd>(Since Linux 2.6.12, but see BUGS) Specifies a ceiling on the real-time priority that may be set for this process using sched_setscheduler(2) and sched_setparam(2).</dd>
<dt>RLIMIT_RTTIME</dt>
<dd>(Since Linux 2.6.25) Specifies a limit on the amount of CPU time that a process scheduled under a real-time scheduling policy may consume without making a blocking system call.  For the purpose of this limit, each time a process makes a blocking system call, the count of its consumed CPU time is reset to zero.  The CPU time count is not reset if the process continues trying to use the CPU but is preempted, its time slice expires, or it calls sched_yield(2). Upon reaching the soft limit, the process is sent a SIGXCPU signal.  If the process catches or ignores this signal and continues consuming CPU time, then SIGXCPU will be generated once each second until the hard limit is reached, at which point the process is sent a SIGKILL signal.  The intended use of this limit is to stop a runaway real-time process from locking up the system.</dd>
<dt>RLIMIT_SIGPENDING</dt>
<dd>(Since Linux 2.6.8) Specifies the limit on the number of signals that may be queued for the real user ID of the calling process.  Both standard and real-time signals are counted for the purpose of checking this limit.  However, the limit is only enforced for sigqueue(2); it is always possible to use kill(2) to queue one instance of any of the signals that are not already queued to the process.</dd>
<dt>RLIMIT_STACK</dt>
<dd>The maximum size of the process stack, in bytes.  Upon reaching this limit, a SIGSEGV signal is generated.  To handle this signal, a process must employ an alternate signal stack (sigaltstack(2)).</dd>
</dl>

<p><a id="ulimit-examples" name="ulimit-examples"></a></p><h4>ulimit Examples</h4>
<p>Turn off core dumps</p>
<pre>ulimit -S -c 0</pre>








<h2>More Reading</h2>
<ul>
<li>Please see the <a href="http://pagesperso-orange.fr/sebastien.godard/">SYSSTAT Utilities Home for more performance monitoring tools</a> like sar, sadf, mpstat, iostat, pidstat and sa tools.</li>
<li><a href="http://gaarai.com/2009/03/06/multitasking-from-the-linux-command-line-plus-process-prioritization/">Multitasking from the Linux Command Line + Process Prioritization</a></li>
</ul>


<h2>Man Pages</h2>
<ol>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/sched_setscheduler.2.html">sched_setscheduler</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man7/cpuset.7.html">cpuset</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html">signal</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html">getrlimit</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man3/ulimit.3.html">ulimit</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/ioprio_get.2.html">ioprio_get</a></li>
<li><a href="http://www.kernel.org/doc/man-pages/online/pages/man2/ioprio_set.2.html">ioprio_set</a></li>
</ol>


<h2>Kernel Documentation</h2>
<ul>
<li><a href='http://uploads.askapache.com/2009/08/sched-stats.txt'>information on schedstats (Linux Scheduler Statistics)</a></li>
<li><a href='http://uploads.askapache.com/2009/08/sched-rt-group.txt'>real-time group scheduling</a></li>
<li><a href='http://uploads.askapache.com/2009/08/sched-nice-design.txt'>How and why the scheduler's nice levels are implemented</a></li>
<li><a href='http://uploads.askapache.com/2009/08/sched-domains.txt'>information on scheduling domains</a></li>
<li><a href='http://uploads.askapache.com/2009/08/sched-design-CFS.txt'>goals, design and implementation of the Complete Fair Scheduler</a></li>
</ul>



<h2>Future Discussions:</h2>
<p><a href="http://www.cuddletech.com/blog/pivot/entry.php?id=820">IO Benchmarking: How, Why and With What</a></p><p><a href="http://www.askapache.com/optimize/optimize-nice-ionice.html"></a><a href="http://www.askapache.com/optimize/optimize-nice-ionice.html">Optimizing Servers and Processes for Speed with ionice, nice, ulimit</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/optimize/optimize-nice-ionice.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>An AskApache Plugin Upgrade to Rule them All</title>
		<link>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html</link>
		<comments>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html#comments</comments>
		<pubDate>Wed, 29 Jul 2009 17:59:07 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=3062</guid>
		<description><![CDATA[<p><a class="IFL" href="http://uploads.askapache.com/2009/07/apache-server-status.png"><img src="http://uploads.askapache.com/2009/07/apache-server-status-350x164.png" alt="apache-server-status" title="apache-server-status" width="350" height="164" class="alignnone size-medium wp-image-3070" /></a>So my blog as been rather quiet for almost a year now, and very few updates if any have been released for my Password Protection PLugin, my Google 404 Plugin, and definately not for my AskApache CrazyCache plugin, which I will be releasing last...  So for all of you who've helped me out by sending me suggestions and notifying me of errors and sticking with it...  Just wanted to <strong>say sorry about that, and thanks for all the great ideas.. </strong> Well, I've been sticking with it as well believe it our not.  I manage to get free days once in a while, and then its <strong>time to jam</strong>.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html"></a><a href="http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html"><cite>AskApache.com</cite></a></p><p><a class="IFL" href="http://uploads.askapache.com/2009/07/apache-server-status.png"><img src="http://uploads.askapache.com/2009/07/apache-server-status-350x164.png" alt="An AskApache Plugin Upgrade to Rule them All" title="apache-server-status" width="350" height="164" class="alignnone size-medium wp-image-3070" /></a>So my blog as been rather quiet for almost a year now, and very few updates if any have been released for my Password Protection PLugin, my Google 404 Plugin, and definately not for my AskApache CrazyCache plugin, which I will be releasing last...  So for all of you who've helped me out by sending me suggestions and notifying me of errors and sticking with it...  Just wanted to <strong>say sorry about that, and thanks for all the great ideas.. </strong> Well, I've been sticking with it as well believe it our not.  I manage to get free days once in a while, and then its <strong>time to jam</strong>.</p>
 <p>I've used just about every CMS/Blog/Forum/Trac/Gallery/etc) and really didn't like a lot of the way they coded...  I could use php but I didn't KNOW php.. so I've had to learn php also, and it was tough to learn the advanced class usage and all the other language specific (but similar) constructs for php.  It was especially difficult (but fun and challenging) to program so as to be compatible with php4 and php5 (Such is WordPress).    But I kept at it, and soon you can decide for yourself what to make of it.</p>
<p>I can code in plenty of languages (bash, lua, windows .bat and vbs,  ocaml, big fan of all things shell) and can work my way through C and even sorta somewhat with assembly.  Assembly is the hardest, by far,  I'm into easy and powerful languages like Python, Javascript, perl, php, ruby, and CGI. I've used PHP for a long time to do various things,  but never to build software projects like this.  Once I noticed WordPress's core .php files and the excellent programming I wanted to try and learn hot to do it.   The WordPress code is some of the best I've seen.  It appears the way they built it was planned, and not just dreamt up while typing that I can't help but do.    Every time I read through the core code I learn a new trick or very nice way to do something.  Those guys are really good, and I think WordPress is going to dominate for a long long time.</p>


<h2>The Strategy</h2>
<p>The Password Protection (passpro) plugin has a lot of complex stuff going on, especially for a newbie to PHP and WordPress like me, so after refactoring the whole thing at least 5 times I decided to modify my approach, and wrote the AskApache Google 404 Plugin as a way to practice on a simpler piece of code, while at the same time providing a plugin of value.   Eventually I stopped thinking I could just code the whole thing in one sit-down with a stream-of-consciousness, and had to instead modularize the code and focus in on each part before moving to the next (I go without a plan because its fun, just not the most productive, but again, I'm not a programmer in the scientific sense.).</p>
<p>So I decided I had to really learn how WordPress Plugins work, filters, hooks, actions, and basically comfortability at reverse-engineering code, (Im a beginner for the last time), and so with the upcoming release of the AskApache Google 404 Plugin I have succeeded in making an incredibly stable plugin.  That way I only have to worry about what the aapasspro plugin is doing, instead of trying to fit it into a framework.  </p>


<h2>AskApache Google 404 Upgrade</h2>
<p>I think its rather unusual to develop a nice plugin like this 404 handler merely for the purpose of improving upon another plugin, but hey it worked.  As of <em>08/03/2009 14:06PM EST</em> I have about 1 hour left of finishing touches to release this upgrade.  But as you cantell by my badly edited posts, I don't have a lot of time to myself.  An hour here and there is about it.  So it could be up to 2 weeks before I actually have the time to commit the release to the repo.  On a sidenote, have you checked out <a href="http://windows7news.com/" title="Windows 7 News">Windows 7 News</a>?  I've been contracted to do some technical work for them and thought they had an excellent site.</p>
<p><a href="http://uploads.askapache.com/2009/07/askapache-google-upgrade-ss1.png"><img src="http://uploads.askapache.com/2009/07/askapache-google-upgrade-ss1-344x350.png" alt="An AskApache Plugin Upgrade to Rule them All" title="askapache-google-upgrade-ss1" width="344" height="350" class="alignnone size-medium wp-image-3139" /></a></p>
<p><a href="http://uploads.askapache.com/2009/07/askapache-google-upgrade-ss2.png"><img src="http://uploads.askapache.com/2009/07/askapache-google-upgrade-ss2-293x350.png" alt="An AskApache Plugin Upgrade to Rule them All" title="askapache-google-upgrade-ss2" width="293" height="350" class="alignnone size-medium wp-image-3138" /></a></p>
<p>But keep in mind, the 404 PLugin is just where I practice for the passpro plugin, which truly does have features that no other software like it has ever had.  I understand the technology behind this plugin, and know it would really have a great impact on improving the Web (esp. WordPress) for all of us, I've just had to learn how to make it.</p>

<h2>AskApache Password Protection</h2>
<p>Probably still a couple weeks away, this plugin is the ultimate culmination of apache hackers dreams, at least those on shared servers (who may be interested in learning how to bypass security of said servers)..  So this is something I have much too fun with doing what I like to do.. network/protocol-level security.  I've examined the source code for many software packages that I use or have used to audit a server's security, and this simple php plugin in most instances can enumerate with accuraccy most of the server's setup in about a minute.  The catch (and the file permission problems I had to find a workaround too) is that this software is launched on the server, not remotely against the server.</p>
<p>Some of the software I examined was whiskers, nessus, nmap, hping, mozilla source, wireshark, ncftp, netcat, etc..  The closest comparison to the socket-level class I've hacked together to those is wireshark.  Except that wireshark only interprets (captures) the data passing over the wire, while this class does that and in fact sends and receives the data like netcat or nmap.  Its really more similar to metasploit, and can easily be used to send hex, binary, ascii, or any type of payload to the remote or local host.</p>


<h2>The Upgrades Begin</h2>
<p>Well I started working on them a long time ago.  Both the Password Protection plugin and the Google 404 plugin needed serious work.   And I finally have it all figured out.  Essentially I would work on one and finish an upgrade, but I just wasn't happy with it and I wold start all over again, refactoring the code.   So as I put the finishing touches on those 2 plugins keep an eye out.  They are major upgrades.   I was able to meet all the goals I had for them, and came up with a lot of more improvements during the process.One of the main things I needed was a socket-level class to perform all kinds of checks and tests on.  I need this also for my crazy cache plugin, which my blog is currently using ,  and I have a 2 more really nice pplugins I use that also needed  access to a network class.  I wrote about what I was doing with fsockopen, and I've been improving on that example ever since.  I use this class to do some really powerful and exciting stuff, but you'll see it soon enough.  As an indication of 'getting it right' for the Password Protection plugin, the plugin will now work on Windows, Apache, IIS, Lighthttpd, and will even work running on a blackberry web server.  So now everyone using wordpress can at least get some security()



<p class="enote">Many of the the other improvements focus on using the fsockopen class and .htaccess tricks to basically enumerate and discover all the different capabilities of your particular server;  That way you can learn about all the features and security that are possible for your specific server, and the securty modules wi8ll be geared for that as well.  FINALLY this plugin is going to be stable, and I just cant wait to see how people react when they learn all great capability their Apache-based Server has that they didn't have a clue about.   Its amazing in that sense, and hackers will love theh way it works.. but your server admins will love it even more because its entirely 100% focused on helping you to set your site up (if you have Apache) to keep spammers out, to keep virii-serving robots and their log-hogging exploit requests and CPU/Mem robiing 404 errors off of your servers for real.  This will have a noticeable affect to whoever is running the server.   As you can tell.. I am pumped!</br></p>


<hr class="C" />
Apache is easy to configure and use, but only when you have root access.  Most people on shared and private hosting aren't even able to view the main config file, let alone execute the Apache binaries to see what features are available and what configuration is being used.<br class="C" /></p>

<p>Apache can only be influenced by the main server configs and by .htaccess files.  Not by php, not by perl, and the main configs are almost never accessible to the masses.  But .htaccess files are.  And many hosting providers allow and enable .htaccess files, a configuration file for your web server.  The advanced features and capabilities of Apache were out of reach for most of us, it just wasn't possible to enumerate or access, and most hosting providers are infamous for their lack of .htaccess (customer) support.  This plugin goes around those problems to give the power back to the people.<br class="C" /></p>y creating custom .htaccess files containing unpublished .htaccess tricks and techniques and combining that with the use of socket-level networking from WordPress (PHP) using <a href="http://www.askapache.com/php/fsockopen-socket.html">fsockopen</a>, we can effectively enumerate and discover an incredible amount of features and settings you will be able to control and use with this plugin.</p>

<p>Here are a few examples of the capabilities of this plugin, some of which I believe no other software can do..  <em>(Open source free to copy!)</em>.</p>
<ol>
<li>Current Version of Apache (<strong>Down to the API Version</strong>)</li>
<li>List of <strong>ALL Modules currently enabled</strong> by Apache (Such as Mod_Rewrite)</li>
<li>List of <strong>ALL Directives enabled by EACH enabled Module.</strong></li>
<li>Enumerate .htaccess Overrides, Context Permissions</li>
<li>Test for any builtin Handlers (like the <a href="http://uploads.askapache.com/2009/07/apache-server-status.png">status handler screenshot</a>)</li>
<li>Configure SSI (<a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security">http://www.askapache.com/htaccess/advanced-htaccess-ssi.html#htaccess-ssi-security</a>)</li>
</ol>


<blockquote cite="http://www.askapache.com/htaccess/password-protection-plugin-status.html"><div class="inote"><cite><a href="http://www.askapache.com/htaccess/password-protection-plugin-status.html"></a></cite><p><strong>March 1, 2009</strong><br /><strong>I would focus on the method that WordPress uses</strong>.  The code they have now (2.8 bleeding-edge) still isn't where it needs to be, but this is some difficult stuff and <strong>they have a brilliant start, it'll work.. just a question of when</strong>.</p>
<p><a class="IFL" href="http://uploads.askapache.com/2009/03/apache-security-model-tall1.png"><img src="http://uploads.askapache.com/2009/03/apache-security-model-tall1-250x123.png" alt="Apache Security Model - In Color" title="apache-security-model-wide" width="250" height="123" /></a><strong>The main issue</strong> with the password protection plugin working for some people and not others is due to <a title="detailed file permission article" href="http://www.askapache.com/security/chmod-stat.html">file permission configurations</a>.  The plugin attempts to write/modify files in your blog's root directory.<br class="C" /></p></div></blockquote>
<hr class="C" />

<blockquote cite="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html"><div class="inote"><cite><a href="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html"></a></cite><p><strong>November 05, 2008</strong><br />To make a long story short, I downloaded each major release of the apache httpd source code starting at version 1.3.0 and finishing with version 2.2.11, I then compiled each version and built a HTTPD from source for all these apache versions.</p>
<div><div style="width:100px;overflow:hidden;float:left;"><ul><li>1.3.0</li><li>1.3.1</li><li>1.3.11</li><li>1.3.12</li><li>1.3.14</li><li>1.3.17</li><li>1.3.19</li><li>1.3.2</li><li>1.3.20</li><li>1.3.22</li><li>1.3.23</li><li>1.3.24</li><li>1.3.27</li><li>1.3.28</li></ul></div><div style="width:100px;overflow:hidden;float:left;"><ul><li>1.3.29</li><li>1.3.3</li><li>1.3.31</li><li>1.3.32</li><li>1.3.33</li><li>1.3.34</li><li>1.3.35</li><li>1.3.36</li><li>1.3.37</li><li>1.3.39</li><li>1.3.4</li><li>1.3.41</li><li>1.3.6</li><li>1.3.9</li></ul></div>
<div style="width:100px;overflow:hidden;float:left;"><ul><li>2.0.35</li><li>2.0.36</li><li>2.0.39</li><li>2.0.40</li><li>2.0.42</li><li>2.0.43</li><li>2.0.44</li><li>2.0.45</li><li>2.0.46</li><li>2.0.47</li><li>2.0.48</li><li>2.0.49</li><li>2.0.50</li><li>2.0.51</li></ul></div><div style="width:150px;overflow:hidden;float:left;"><ul><li>2.0.52</li><li>2.0.53</li><li>2.0.54</li><li>2.0.55</li><li>2.0.58</li><li>2.0.59</li><li>2.0.61</li><li>2.0.63</li><li>2.1.3-beta</li><li>2.1.6-alpha</li><li>2.1.7-beta</li><li>2.1.8-beta</li><li>2.1.9-beta</li></ul></div><div style="width:100px;overflow:hidden;float:left;"><ul><li>2.2.0</li><li>2.2.10</li><li>2.2.2</li><li>2.2.3</li><li>2.2.4</li><li>2.2.6</li><li>2.2.8</li><li>2.2.9</li><li><strong>2.2.10</strong></li><li><strong>2.2.11</strong></li></ul></div><br class="C" /></div>
<p>Then I went through each version and determined the compatible modules for that version, and I'm pretty confident that I was also able to find each and every directive allowed by the compatible modules for that version (including core directives).  See <a href="http://www.askapache.com/htaccess/htaccess.html#htaccess-directives">.htaccess directive list</a>.  Basically I can now test a server using a variety of methods and determine almost 100% accurately what version of Apache (down to the API) is running, what modules (and versions) are enabled, and each and every directive that is allowed or disallowed for that version.  So this is so awesome because now we can enable all sorts of additional security features.</p>
</div>
</blockquote>
<hr class="C" />




<blockquote cite="http://www.askapache.com/htaccess/htaccess.html#htaccess-modules"><cite><a href="http://www.askapache.com/htaccess/htaccess.html#htaccess-modules">Htaccess enabled Modules</a></cite><p>Here are most of the modules that come with Apache.  Each one can have new commands that can be used in .htaccess file scopes.</p>
<p><a href="http://www.askapache.com/servers/mod_actions.c.html">mod_actions</a>, <a href="http://www.askapache.com/servers/mod_alias.c.html">mod_alias</a>, <a href="http://www.askapache.com/servers/mod_asis.c.html">mod_asis</a>, <a href="http://www.askapache.com/servers/mod_auth_basic.c.html">mod_auth_basic</a>, <a href="http://www.askapache.com/servers/mod_auth_digest.c.html">mod_auth_digest</a>, <a href="http://www.askapache.com/servers/mod_authn_anon.c.html">mod_authn_anon</a>, <a href="http://www.askapache.com/servers/mod_authn_dbd.c.html">mod_authn_dbd</a>, <a href="http://www.askapache.com/servers/mod_authn_dbm.c.html">mod_authn_dbm</a>, <a href="http://www.askapache.com/servers/mod_authn_default.c.html">mod_authn_default</a>, <a href="http://www.askapache.com/servers/mod_authn_file.c.html">mod_authn_file</a>, <a href="http://www.askapache.com/servers/mod_authz_dbm.c.html">mod_authz_dbm</a>, <a href="http://www.askapache.com/servers/mod_authz_default.c.html">mod_authz_default</a>, <a href="http://www.askapache.com/servers/mod_authz_groupfile.c.html">mod_authz_groupfile</a>, <a href="http://www.askapache.com/servers/mod_authz_host.c.html">mod_authz_host</a>, <a href="http://www.askapache.com/servers/mod_authz_owner.c.html">mod_authz_owner</a>, <a href="http://www.askapache.com/servers/mod_authz_user.c.html">mod_authz_user</a>, <a href="http://www.askapache.com/servers/mod_autoindex.c.html">mod_autoindex</a>, <a href="http://www.askapache.com/servers/mod_cache.c.html">mod_cache</a>, <a href="http://www.askapache.com/servers/mod_cern_meta.c.html">mod_cern_meta</a>, <a href="http://www.askapache.com/servers/mod_cgi.c.html">mod_cgi</a>, <a href="http://www.askapache.com/servers/mod_dav.c.html">mod_dav</a>, <a href="http://www.askapache.com/servers/mod_dav_fs.c.html">mod_dav_fs</a>, <a href="http://www.askapache.com/servers/mod_dbd.c.html">mod_dbd</a>, <a href="http://www.askapache.com/servers/mod_deflate.c.html">mod_deflate</a>, <a href="http://www.askapache.com/servers/mod_dir.c.html">mod_dir</a>, <a href="http://www.askapache.com/servers/mod_disk_cache.c.html">mod_disk_cache</a>, <a href="http://www.askapache.com/servers/mod_dumpio.c.html">mod_dumpio</a>, <a href="http://www.askapache.com/servers/mod_env.c.html">mod_env</a>, <a href="http://www.askapache.com/servers/mod_expires.c.html">mod_expires</a>, <a href="http://www.askapache.com/servers/mod_ext_filter.c.html">mod_ext_filter</a>, <a href="http://www.askapache.com/servers/mod_file_cache.c.html">mod_file_cache</a>, <a href="http://www.askapache.com/servers/mod_filter.c.html">mod_filter</a>, <a href="http://www.askapache.com/servers/mod_headers.c.html">mod_headers</a>, <a href="http://www.askapache.com/servers/mod_ident.c.html">mod_ident</a>, <a href="http://www.askapache.com/servers/mod_imagemap.c.html">mod_imagemap</a>, <a href="http://www.askapache.com/servers/mod_include.c.html">mod_include</a>, <a href="http://www.askapache.com/servers/mod_info.c.html">mod_info</a>, <a href="http://www.askapache.com/servers/mod_log_config.c.html">mod_log_config</a>, <a href="http://www.askapache.com/servers/mod_log_forensic.c.html">mod_log_forensic</a>, <a href="http://www.askapache.com/servers/mod_logio.c.html">mod_logio</a>, <a href="http://www.askapache.com/servers/mod_mem_cache.c.html">mod_mem_cache</a>, <a href="http://www.askapache.com/servers/mod_mime.c.html">mod_mime</a>, <a href="http://www.askapache.com/servers/mod_mime_magic.c.html">mod_mime_magic</a>, <a href="http://www.askapache.com/servers/mod_negotiation.c.html">mod_negotiation</a>, <a href="http://www.askapache.com/servers/mod_proxy.c.html">mod_proxy</a>, <a href="http://www.askapache.com/servers/mod_proxy_ajp.c.html">mod_proxy_ajp</a>, <a href="http://www.askapache.com/servers/mod_proxy_balancer.c.html">mod_proxy_balancer</a>, <a href="http://www.askapache.com/servers/mod_proxy_connect.c.html">mod_proxy_connect</a>, <a href="http://www.askapache.com/servers/mod_proxy_ftp.c.html">mod_proxy_ftp</a>, <a href="http://www.askapache.com/servers/mod_proxy_http.c.html">mod_proxy_http</a>, <a href="http://www.askapache.com/servers/mod_rewrite.c.html">mod_rewrite</a>, <a href="http://www.askapache.com/servers/mod_setenvif.c.html">mod_setenvif</a>, <a href="http://www.askapache.com/servers/mod_speling.c.html">mod_speling</a>, <a href="http://www.askapache.com/servers/mod_ssl.c.html">mod_ssl</a>, <a href="http://www.askapache.com/servers/mod_status.c.html">mod_status</a>, <a href="http://www.askapache.com/servers/mod_substitute.c.html">mod_substitute</a>, <a href="http://www.askapache.com/servers/mod_unique_id.c.html">mod_unique_id</a>, <a href="http://www.askapache.com/servers/mod_userdir.c.html">mod_userdir</a>, <a href="http://www.askapache.com/servers/mod_usertrack.c.html">mod_usertrack</a>, <a href="http://www.askapache.com/servers/mod_version.c.html">mod_version</a>, <a href="http://www.askapache.com/servers/mod_vhost_alias.c.html">mod_vhost_alias</a></p></blockquote>
<hr class="C" /><hr class="C" />




<h2>Debugging HTTP protocol</h2>
<p>Check this out!  I'm particularly happy about this feature, which outputs an exact trace of any requests made by the plugin (such as during the testing phase) by saving the actual raw data sent out on the wire using fsockopen, RX and TX.  This is useful for a number of reasons, viewing your headers, finding Redirect Loops, testing RewriteRules, and following the request hop-by-hop for debugging.  The below example shows 2 requests for 2 URIs.  The first URI is protected using Digest Authentication, the 2nd shows Basic.</p>
<pre> ______________
|  RAW TRACE   |
==================================================================================================================================
GET /htaccess/index.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
&nbsp;
HTTP/1.1 401 Authorization Required
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
WWW-Authenticate: Digest realm="do or die", nonce="03328f3ec7c7b", algorithm=MD5, domain="/", qop="auth"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 882
Connection: close
Content-Type: text/html; charset=UTF-8
&nbsp;
GET /htaccess/index.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
Authorization: Digest username="test",realm="do or die",nonce="03328f3ec7c7b",uri="/htaccess/index.txt?testing=query",
cnonce="82d057852a9dc497",nc=00000001,algorithm=MD5,response="9d476e9ea3",qop="auth"
&nbsp;
HTTP/1.1 200 OK
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
Authentication-Info: rspauth="9051b01ee26dd62b3e2b40dada694f45", cnonce="82d057852a9dc497", nc=00000001, qop=auth
Last-Modified: Tue, 21 Jul 2009 23:56:00 GMT
Accept-Ranges: bytes
Cache-Control: max-age=3600
Expires: Wed, 22 Jul 2009 07:29:58 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 27
Connection: close
Content-Type: text/plain; charset=UTF-8
```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
&nbsp;
 ______________
|  RAW TRACE   |
==================================================================================================================================
GET /htaccess/po.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
&nbsp;
HTTP/1.1 401 Authorization Required
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
WWW-Authenticate: Basic realm="Po Pimping"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 878
Connection: close
Content-Type: text/html; charset=UTF-8
&nbsp;
GET /htaccess/po.txt?testing=query HTTP/1.1
Host: www.askapache.com
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1) AA_PassPro/1.9 (http://www.askapache.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://www.askapache.com/
Authorization: Basic adfAGAltcA==
&nbsp;
HTTP/1.1 200 OK
Date: Wed, 22 Jul 2009 06:29:58 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 05:54:39 GMT
Accept-Ranges: bytes
Cache-Control: max-age=3600
Expires: Wed, 22 Jul 2009 07:29:58 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 27
Connection: close
Content-Type: text/plain; charset=UTF-8
```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````</pre>














<h2>.htaccess Directives</h2>
<p>AcceptFilter, AcceptMutex, AcceptPathInfo, AccessFileName, Action, AddAlt, AddAltByEncoding, AddAltByType, AddCharset, AddDefaultCharset, AddDescription, AddEncoding, AddHandler, AddIcon, AddIconByEncoding, AddIconByType, AddInputFilter, AddLanguage, AddModuleInfo, AddOutputFilter, AddOutputFilterByType, AddType, Alias, AliasMatch, AllowCONNECT, AllowEncodedSlashes, AllowOverride, Anonymous, Anonymous_Authoritative, Anonymous_LogEmail, Anonymous_MustGiveEmail, Anonymous_NoUserID, Anonymous_NoUserId, Anonymous_VerifyEmail, AssignUserId, AuthAuthoritative, AuthBasicAuthoritative, AuthBasicProvider, AuthDBDUserPWQuery, AuthDBDUserRealmQuery, AuthDBM, AuthDBMAuthoritative, AuthDBMGroupFile, AuthDBMType, AuthDBMUserFile, AuthDefaultAuthoritative, AuthDigestAlgorithm, AuthDigestDomain, AuthDigestFile, AuthDigestGroupFile, AuthDigestNcCheck, AuthDigestNonceFormat, AuthDigestNonceLifetime, AuthDigestProvider, AuthDigestQop, AuthDigestShmemSize, AuthGroupFile, AuthLDAPAuthzEnabled, AuthLDAPBindDN, AuthLDAPBindON, AuthLDAPBindPassword, AuthLDAPCharsetConfig, AuthLDAPCompareDNOnServer, AuthLDAPDereferenceAliases, AuthLDAPEnabled, AuthLDAPFrontPageHack, AuthLDAPGroupAttribute, AuthLDAPGroupAttributeIsDN, AuthLDAPRemoteUserAttribute, AuthLDAPRemoteUserIsDN, AuthLDAPStartTLS, AuthLDAPURL, AuthLDAPUrl, AuthName, AuthType, AuthUserFile, AuthzDBMAuthoritative, AuthzDBMType, AuthzDefaultAuthoritative, AuthzGroupFileAuthoritative, AuthzLDAPAuthoritative, AuthzOwnerAuthoritative, AuthzUserAuthoritative, BS2000Account, BalancerMember, BrowserMatch, BrowserMatchNoCase, BufferedLogs, CGIMapExtension, CacheDefaultExpire, CacheDirLength, CacheDirLevels, CacheDisable, CacheEnable, CacheExpiryCheck, CacheFile, CacheForceCompletion, CacheGcClean, CacheGcDaily, CacheGcInterval, CacheGcMemUsage, CacheGcUnused, CacheIgnoreCacheControl, CacheIgnoreHeaders, CacheIgnoreNoLastMod, CacheLastModifiedFactor, CacheMaxExpire, CacheMaxFileSize, CacheMaxStreamingBuffer, CacheMinFileSize, CacheNegotiatedDocs, CacheRoot, CacheSize, CacheStoreNoStore, CacheStorePrivate, CacheTimeMargin, CharsetDefault, CharsetOptions, CharsetSourceEnc, CheckCaseOnly, CheckSpelling, ChildPerUserId, ContentDigest, CookieDomain, CookieExpires, CookieLog, CookieName, CookieStyle, CookieTracking, CoreDumpDirectory, CustomLog, DAV, DAVDepthInfinity, DAVGenericLockDB, DAVMinTimeout, DBDExptime, DBDKeep, DBDMax, DBDMin, DBDParams, DBDPersist, DBDPrepareSQL, DBDriver, Dav, DavDepthInfinity, DavGenericLockDB, DavLockDB, DavMinTimeout, DefaultIcon, DefaultLanguage, DefaultType, DeflateBufferSize, DeflateCompressionLevel, DeflateFilterNote, DeflateMemLevel, DeflateWindowSize, Directory, DirectoryIndex, DirectoryMatch, DirectorySlash, DocumentRoot, DumpIOInput, DumpIOOutput, EnableExceptionHook, EnableMMAP, EnableSendfile, ErrorDocument, ErrorLog, Example, ExpiresActive, ExpiresByType, ExpiresDefault, ExtFilterDefine, ExtFilterOptions, ExtendedStatus, FancyIndexing, FileETag, Files, FilesMatch, FilterChain, FilterDeclare, FilterProtocol, FilterProvider, FilterTrace, ForceLanguagePriority, ForceType, ForensicLog, GprofDir, GracefulShutdownTimeout, Group, Header, HeaderName, HostNameLookups, HostnameLookups, ISAIPFakeAsync, ISAPIAppendLogToErrors, ISAPIAppendLogToQuery, ISAPICacheFile, ISAPIFakeAsync, ISAPILogNotSupported, ISAPIReadAheadBuffer, IdentityCheck, IdentityCheckTimeout, IfDefine, IfModule, IfVersion, ImapBase, ImapDefault, ImapMenu, Include, IndexIgnore, IndexOptions, IndexOrderDefault, IndexStyleSheet, KeepAlive, KeepAliveTimeout, LDAPCacheEntries, LDAPCacheTTL, LDAPCertDBPath, LDAPConnectionTimeout, LDAPOpCacheEntries, LDAPOpCacheTTL, LDAPSharedCacheFile, LDAPSharedCacheSize, LDAPTrustedClientCert, LDAPTrustedGlobalCert, LDAPTrustedMode, LDAPVerifyServerCert, LanguagePriority, Limit, LimitExcept, LimitInternalRecursion, LimitRequestBody, LimitRequestFields, LimitRequestFieldsize, LimitRequestLine, LimitXMLRequestBody, Listen, ListenBacklog, LoadFile, LoadModule, Location, LocationMatch, LockFile, LogFormat, LogLevel, MCacheMaxObjectCount, MCacheMaxObjectSize, MCacheMaxStreamingBuffer, MCacheMinObjectSize, MCacheRemovalAlgorithm, MCacheSize, MMapFile, MaxClients, MaxKeepAliveRequests, MaxMemFree, MaxRequestsPerChild, MaxSpareServers, MaxSpareThreads, MaxSpareThreadsPerChild, MaxThreads, MetaDir, MetaFiles, MetaSuffix, MimeMagicFile, MinSpareServers, MinSpareThreads, ModMimeUsePathInfo, MultiviewsMatch, NWSSLTrustedCerts, NWSSLUpgradeable, NameVirtualHost, NoProxy, NumServers, Options, PassEnv, PerlAccessHandler, PerlAuthenHandler, PerlAuthzHandler, PerlChildExitHandler, PerlChildInitHandler, PerlCleanupHandler, PerlDispatchHandler, PerlFixupHandler, PerlFreshRestart, PerlHandler, PerlHeaderParserHandler, PerlInitHandler, PerlLogHandler, PerlModule, PerlPassEnv, PerlPostReadRequestHandler, PerlRequire, PerlRestartHandler, PerlSendHeader, PerlSetEnv, PerlSetVar, PerlSetupEnv, PerlTaintCheck, PerlTransHandler, PerlTypeHandler, PerlWarn, PidFile, Port, Protocol, ProtocolEcho, Proxy, ProxyBadHeader, ProxyBlock, ProxyDomain, ProxyErrorOverride, ProxyFtpDirCharset, ProxyIOBufferSize, ProxyMatch, ProxyMaxForwards, ProxyPass, ProxyPassInterpolateEnv, ProxyPassMatch, ProxyPassReverse, ProxyPassReverseCookieDomain, ProxyPassReverseCookiePath, ProxyPreserveHost, ProxyReceiveBufferSize, ProxyRemote, ProxyRemoteMatch, ProxyRequests, ProxySet, ProxyStatus, ProxyTimeout, ProxyVia, RLimitCPU, RLimitMEM, RLimitNPROC, ReadmeName, Redirect, RedirectMatch, RedirectPermanent, RedirectTemp, RemoveCharset, RemoveEncoding, RemoveHandler, RemoveInputFilter, RemoveLanguage, RemoveOutputFilter, RemoveType, RequestHeader, Require, RewriteBase, RewriteCond, RewriteEngine, RewriteLock, RewriteLog, RewriteLogLevel, RewriteMap, RewriteOptions, RewriteRule, SSIAccessEnable, SSIEndTag, SSIErrorMsg, SSIStartTag, SSITimeFormat, SSIUndefinedEcho, SSLCACertificateFile, SSLCACertificatePath, SSLCADNRequestFile, SSLCADNRequestPath, SSLCARevocationFile, SSLCARevocationPath, SSLCertificateChainFile, SSLCertificateFile, SSLCertificateKeyFile, SSLCipherSuite, SSLCryptoDevice, SSLEngine, SSLHonorCipherOrder, SSLLog, SSLLogLevel, SSLMutex, SSLOptions, SSLPassPhraseDialog, SSLProtocol, SSLProxyCACertificateFile, SSLProxyCACertificatePath, SSLProxyCARevocationFile, SSLProxyCARevocationPath, SSLProxyCipherSuite, SSLProxyEngine, SSLProxyMachineCertificateFile, SSLProxyMachineCertificatePath, SSLProxyProtocol, SSLProxyVerify, SSLProxyVerifyDepth, SSLRandomSeed, SSLRequire, SSLRequireSSL, SSLSessionCache, SSLSessionCacheTimeout, SSLUserName, SSLVerifyClient, SSLVerifyDepth, Satisfy, ScoreBoardFile, Script, ScriptAlias, ScriptAliasMatch, ScriptInterpreterSource, ScriptLog, ScriptLogBuffer, ScriptLogLength, ScriptStock, SecureListen, SendBufferSize, ServerAdmin, ServerAlias, ServerLimit, ServerName, ServerPath, ServerRoot, ServerSignature, ServerTokens, SetEnv, SetEnvIf, SetEnvIfNoCase, SetHandler, SetInputFilter, SetOutputFilter, StartServers, StartThreads, Substitute, SuexecUserGroup, ThreadLimit, ThreadStackSize, ThreadsPerChild, TimeOut, Timeout, TraceEnable, TransferLog, TypeAuthDBMUserFile, TypesConfig, UnsetEnv, UseCanonicalName, UseCanonicalPhysicalPort, User, UserDir, VirtualDocumentRoot, VirtualDocumentRootIP, VirtualHost, VirtualScriptAlias, VirtualScriptAliasIP, Win32DisableAcceptEx, XBitHack, allow, deny, order, php_admin_flag, php_admin_value, php_flag, php_value</p>



<p class="anote">You can view the <a href="http://www.askapache.com/htaccess/htaccess-security-block-spam-hackers.html">plugins home page</a>, <a href="http://www.askapache.com/wordpress/htaccess-password-protect.html#aadl">old</a>, or <a href="http://wordpress.org/extend/plugins/askapache-password-protect/">view it on the wordpress.org site</a>.</p><p><a href="http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html"></a><a href="http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html">An AskApache Plugin Upgrade to Rule them All</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/wordpress/an-askapache-plugin-upgrade-to-rule-them-all.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>AskApache Debug Viewer Plugin for WordPress</title>
		<link>http://www.askapache.com/wordpress/debug-viewer-plugin.html</link>
		<comments>http://www.askapache.com/wordpress/debug-viewer-plugin.html#comments</comments>
		<pubDate>Mon, 06 Apr 2009 03:53:31 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2502</guid>
		<description><![CDATA[<p><a class="IFL" href='http://uploads.askapache.com/2009/04/screenshot-1.png' title='screenshot-1'><img src="http://uploads.askapache.com/2009/04/screenshot-1-350x306.png" alt="screenshot-1" title="screenshot-1" width="350" height="306" /></a><strong>The story behind this plugin is sorta wack</strong>, but in a good way :).  While doing tons of security research on permissions, authorization, access, etc.. for the <a href="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html">Password Protection plugin</a> (<em><a href="http://www.askapache.com/htaccess/password-protection-plugin-status.html">still being worked on</a></em>), I needed to have unheard of debugging capabilities while working on the plugin on the various websites, webhosts, and test servers that I use to test in different environments.  So I hacked together a bunch of php code that helped me debug, actually I pretty much went overkill and tried to get as much debugging info as programmatically possible, and it ended up being so much code that I took it out of my Password Protection code and made it its own plugin.<br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/wordpress/debug-viewer-plugin.html"></a><a href="http://www.askapache.com/wordpress/debug-viewer-plugin.html"><cite>AskApache.com</cite></a></p><p><a href="#php-debug-screenshots">Screen Shots</a> | <a href="#php-debug-functions">PHP Debug Functions</a></p>
<p><a class="IFL" href='http://uploads.askapache.com/2009/04/screenshot-1.png' title='screenshot-1'><img src="http://uploads.askapache.com/2009/04/screenshot-1-350x306.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-1" width="350" height="306" /></a><strong>The story behind this plugin is sorta wack</strong>, but in a good way :).  While doing tons of security research on permissions, authorization, access, etc.. for the <a href="http://www.askapache.com/htaccess/htaccess-plugin-blocks-spam-hackers-and-password-protects-blog.html">Password Protection plugin</a> (<em><a href="http://www.askapache.com/htaccess/password-protection-plugin-status.html">still being worked on</a></em>), I needed to have unheard of debugging capabilities while working on the plugin on the various websites, webhosts, and test servers that I use to test in different environments.  So I hacked together a bunch of php code that helped me debug, actually I pretty much went overkill and tried to get as much debugging info as programmatically possible, and it ended up being so much code that I took it out of my Password Protection code and made it its own plugin.<br class="C" /></p>

<p>I've been using it for several months now while working on a plugin or diagnosing some issue, and decided that I'd share it with everyone.  Hopefully it will help other plugin authors and php programmers in general to start writing more robust and error-proof code, which would in turn help me!  To help those not using WordPress, I've included most of the debugging functions below, but you'll need the AskApacheDebug class for them to work.  Hope you find it useful!  I do.  <a href="http://wordpress.org/extend/plugins/askapache-debug-viewer/">Download AskApache Debug Viewer</a></p>
<hr class="C" />


<h2><a name="php-debug-screenshots" id="php-debug-screenshots"></a>Screenshots and Debug Output</h2>
<p>The plugin outputs the debugging info in the admin footer by hooking into the 'in_admin_footer' action.<br /><a href='http://uploads.askapache.com/2009/04/screenshot-2.png' title='screenshot-2'><img src="http://uploads.askapache.com/2009/04/screenshot-2.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-2" /></a></p>

<p><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-3.png' title='screenshot-3'><img width="341" height="350" src="http://uploads.askapache.com/2009/04/screenshot-3-341x350.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-3" /></a><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-4.png' title='screenshot-4'><img width="350" height="170" src="http://uploads.askapache.com/2009/04/screenshot-4-350x170.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-4" /></a><br class="C" /></p>
<p><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-5.png' title='screenshot-5'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-5-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-5" /></a><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-6.png' title='screenshot-6'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-6-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-6" /></a><br class="C" /></p>
<p><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-7.png' title='screenshot-7'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-7-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-7" /></a><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-8.png' title='screenshot-8'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-8-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-8" /></a><br class="C" /></p>
<p><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-9.png' title='screenshot-9'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-9-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-9" /></a><a class="FL" style="border-right:5px solid #FFF;" href='http://uploads.askapache.com/2009/04/screenshot-10.png' title='screenshot-10'><img width="350" height="285" src="http://uploads.askapache.com/2009/04/screenshot-10-350x285.png" alt="AskApache Debug Viewer Plugin for WordPress" title="screenshot-10" /></a><br class="C" /></p>




<h2><a name="php-debug-functions" id="php-debug-functions"></a>PHP Debugging Functions</h2>
<p>Ok so for those interested more in the php flavor, here are a few of the functions that produce the debugging output.  I'll start with my customized _stat function, which took a lot of research to write, but you can read that story at <a href="http://www.askapache.com/security/chmod-stat.html">Chmod, Umask, Stat, Fileperms, and File Permissions</a>.</p>

<pre>function _stat($fl)
{
  static $ftypes = false;
  if (!$ftypes)
  {
    $this-&gt;logg(__FUNCTION__ . &#039;:&#039; . __LINE__);
    $ftypes = array(S_IFSOCK =&gt; &#039;ssocket&#039;, S_IFLNK =&gt; &#039;llink&#039;, S_IFREG =&gt; &#039;-file&#039;, S_IFBLK =&gt; &#039;bblock&#039;, S_IFDIR =&gt; &#039;ddir&#039;, S_IFCHR =&gt; &#039;cchar&#039;, S_IFIFO =&gt; &#039;pfifo&#039;);
  }
&nbsp;
  $s = $ss = array();
  if (($ss = stat($fl)) === false) return $this-&gt;logg(__FUNCTION__ . &#039;:&#039; . __LINE__ . " Couldnt stat {$fl}", 0);
  $p = $ss[&#039;mode&#039;];
  $t = decoct($p &amp; S_IFMT);
  $q = octdec($t);
  $type = (array_key_exists($q, $ftypes)) ? substr($ftypes[$q], 0, 1) : &#039;?&#039;;
$s = array(
&#039;filename&#039; =&gt; $fl,
&nbsp;
&#039;human&#039; =&gt; ($type .
(($p &amp; S_IRUSR) ? &#039;r&#039; : &#039;-&#039;) . (($p &amp; S_IWUSR) ? &#039;w&#039; : &#039;-&#039;) . (($p &amp; S_ISUID) ? (($p &amp; S_IXUSR) ? &#039;s&#039; : &#039;S&#039;) : (($p &amp; S_IXUSR) ? &#039;x&#039; : &#039;-&#039;)) .
(($p &amp; S_IRGRP) ? &#039;r&#039; : &#039;-&#039;) . (($p &amp; S_IWGRP) ? &#039;w&#039; : &#039;-&#039;) . (($p &amp; S_ISGID) ? (($p &amp; S_IXGRP) ? &#039;s&#039; : &#039;S&#039;) : (($p &amp; S_IXGRP) ? &#039;x&#039; : &#039;-&#039;)) .
(($p &amp; S_IROTH) ? &#039;r&#039; : &#039;-&#039;) . (($p &amp; S_IWOTH) ? &#039;w&#039; : &#039;-&#039;) . (($p &amp; S_ISVTX) ? (($p &amp; S_IXOTH) ? &#039;t&#039; : &#039;T&#039;) : (($p &amp; S_IXOTH) ? &#039;x&#039; : &#039;-&#039;))),
&#039;octal&#039; =&gt; sprintf("%o", ($ss[&#039;mode&#039;] &amp; 007777)),
&#039;hex&#039; =&gt; sprintf("0x%x", $ss[&#039;mode&#039;]),
&#039;decimal&#039; =&gt; sprintf("%d", $ss[&#039;mode&#039;]),
&#039;binary&#039; =&gt; sprintf("%b", $ss[&#039;mode&#039;]),
&#039;base_convert&#039; =&gt; base_convert($ss[&#039;mode&#039;],10,8),
&#039;fileperms&#039; =&gt; fileperms($fl),
&#039;mode&#039; =&gt; $p,
&nbsp;
&#039;type_octal&#039; =&gt; sprintf("%07o", $q),  &#039;fileuid&#039; =&gt; $ss[&#039;uid&#039;],
&nbsp;
&#039;type&#039; =&gt; $type,
&#039;filegid&#039; =&gt; $ss[&#039;gid&#039;],
&#039;owner_name&#039; =&gt; $this-&gt;get_posix_info(&#039;user&#039;, $ss[&#039;uid&#039;],
&#039;name&#039;),
&#039;group_name&#039; =&gt; $this-&gt;get_posix_info(&#039;group&#039;, $ss[&#039;gid&#039;],
&#039;name&#039;),
&#039;dirname&#039; =&gt; dirname($fl),
&#039;is_file&#039; =&gt; is_file($fl) ? 1 : 0,
&#039;is_dir&#039; =&gt; is_dir($fl) ? 1 : 0,
&#039;is_link&#039; =&gt; is_link($fl) ? 1 : 0,
&#039;is_readable&#039; =&gt; is_readable($fl) ? 1 : 0,
&#039;is_writable&#039; =&gt;
is_writable($fl) ? 1 : 0,&#039;device&#039; =&gt; $ss[&#039;dev&#039;],
&#039;device_number&#039; =&gt; $ss[&#039;rdev&#039;],
&#039;inode&#039; =&gt; $ss[&#039;ino&#039;],
&#039;link_count&#039; =&gt; $ss[&#039;nlink&#039;],
&#039;size&#039; =&gt; $ss[&#039;size&#039;],
&#039;blocks&#039; =&gt; $ss[&#039;blocks&#039;],
&#039;block_size&#039; =&gt; $ss[&#039;blksize&#039;],
&#039;accessed&#039; =&gt; date(&#039;Y M D H:i:s&#039;, $ss[&#039;atime&#039;]),
&#039;modified&#039; =&gt; date(&#039;Y M D H:i:s&#039;, $ss[&#039;mtime&#039;]),
&#039;created&#039; =&gt; date(&#039;Y M D H:i:s&#039;, $ss[&#039;ctime&#039;]),
&#039;mtime&#039; =&gt; $ss[&#039;mtime&#039;], &#039;atime&#039; =&gt; $ss[&#039;atime&#039;],
&#039;ctime&#039; =&gt; $ss[&#039;ctime&#039;], );
  if (is_link($fl)) $s[&#039;link_to&#039;] = readlink($fl);
  if (realpath($fl) != $fl) $s[&#039;real_filename&#039;] = realpath($fl);
&nbsp;
  return $s;
}</pre>



<h3>get_debug_functions</h3>
<p>These are various security and user related information.  Nice.</p>

<pre>function get_debug_functions($vb=false)
{
  $functions=$oa=array();
  $functions = array(
&#039;PHP script Process ID&#039; =&gt; &#039;getmypid&#039;,
&#039;PHP script owners UID&#039; =&gt; &#039;getmyuid&#039;,
&#039;php_sapi_name&#039; =&gt; &#039;php_sapi_name&#039;,
&#039;PHP Uname&#039; =&gt; &#039;php_uname&#039;,
&#039;Zend Version&#039; =&gt; &#039;zend_version&#039;,
&#039;PHP INI Loaded&#039; =&gt; &#039;php_ini_loaded_file&#039;,
&#039;Current Working Directory&#039; =&gt; &#039;getcwd&#039;,
&#039;Last Mod&#039; =&gt; &#039;getlastmod&#039;,
&#039;Script Inode&#039; =&gt; &#039;getmyinode&#039;,
&#039;Script GID&#039; =&gt; &#039;getmygid&#039;,
&#039;Script Owner&#039; =&gt; &#039;get_current_user&#039;,
&#039;Get Rusage&#039; =&gt; &#039;getrusage&#039;,
&#039;Error Reporting&#039; =&gt; &#039;error_reporting&#039;,
&#039;Path name of controlling terminal&#039; =&gt; &#039;posix_ctermid&#039;,
&#039;Error number set by the last posix function that failed&#039; =&gt; &#039;posix_get_last_error&#039;,
&#039;Pathname of current directory&#039; =&gt; &#039;posix_getcwd&#039;,
&#039;posix_getpid&#039; =&gt; &#039;posix_getpid&#039;,
&#039;posix_uname&#039; =&gt; &#039;posix_uname&#039;,
&#039;posix_times&#039; =&gt;&#039;posix_times&#039;,
&#039;posix_errno&#039; =&gt; &#039;posix_errno&#039;,
&#039;Effective group ID of the current process&#039; =&gt; &#039;posix_getegid&#039;,
&#039;Effective user ID of the current process&#039; =&gt; &#039;posix_geteuid&#039;,
&#039;Real group ID of the current process&#039; =&gt; &#039;posix_getgid&#039;,
&#039;Group set of the current process&#039; =&gt; &#039;posix_getgroups&#039;,
&#039;Login name&#039; =&gt; &#039;posix_getlogin&#039;,
&#039;Current process group identifier&#039; =&gt; &#039;posix_getpgrp&#039;,
&#039;Current process identifier&#039; =&gt; &#039;posix_getpid&#039;,
&#039;Parent process identifier&#039; =&gt; &#039;posix_getppid&#039;,
&#039;System Resource limits&#039; =&gt; &#039;posix_getrlimit&#039;,
&#039;Return the real user ID of the current process&#039; =&gt; &#039;posix_getuid&#039;,
&#039;Magic Quotes GPC&#039; =&gt; &#039;get_magic_quotes_gpc&#039;,
&#039;Magic Quotes Runtime&#039; =&gt; &#039;get_magic_quotes_runtime&#039;, );
&nbsp;
  foreach ($functions as $title =&gt; $func_name) {
    $val = &#039;&#039;;
    if ( ( $this-&gt;checkfunction($func_name) &amp;&amp; ($val = $func_name()) !== false) ){
      if (empty($val)) $val=$func_name;
      $oa[$title] = $val;
    }
  }
&nbsp;
  return $oa;
}</pre>


<h3>get_debug_permissions</h3>
<p>This is a function designed to get as much information about file/user/group permissions as possible.</p>

<pre>function get_debug_permissions($vb=false)
{
  $oa=array();
&nbsp;
  $user_info = $this-&gt;get_posix_info(&#039;user&#039;);
  $group_info = $this-&gt;get_posix_info(&#039;group&#039;);
&nbsp;
$functions = array(
&#039;Real Group ID&#039; =&gt; posix_getgid(),
&#039;Effective Group ID&#039; =&gt; posix_getegid(),
&#039;Parent Process ID&#039; =&gt; posix_getppid(),
&#039;Parent Process Group ID&#039; =&gt; posix_getpgid(posix_getppid()),
&#039;Real Process ID&#039; =&gt; posix_getpid(),
&#039;Real Process Group ID&#039; =&gt; posix_getpgid(posix_getpid()),
&#039;Process Effective User ID&#039; =&gt; posix_geteuid(),
&#039;Process Owner Username&#039; =&gt; $user_info[&#039;name&#039;],
&#039;File Owner Username&#039; =&gt; get_current_user(),
&#039;User Info&#039; =&gt; print_r($user_info, 1),
&#039;Group Info&#039; =&gt; print_r($group_info, 1),
&#039;RealPath&#039;  =&gt; realpath(__FILE__),
&#039;SAPI Name&#039; =&gt; (function_exists(&#039;php_sapi_name&#039;)) ? print_r(php_sapi_name(), 1) : &#039;&#039;,
&#039;Posix Process Owner&#039; =&gt; print_r(posix_getpwuid(posix_geteuid()), 1),
&#039;Scanned Ini&#039; =&gt; (function_exists(&#039;php_ini_scanned_files&#039;)) ? str_replace("\n", "", php_ini_scanned_files()) : &#039;&#039;,
&#039;PHP.ini Path&#039; =&gt; get_cfg_var(&#039;cfg_file_path&#039;),
&#039;Sendmail Path&#039; =&gt; get_cfg_var(&#039;sendmail_path&#039;),
&#039;Info about a group by group id&#039; =&gt; posix_getgrgid(posix_getegid()),
&#039;Process group id for Current process&#039; =&gt; posix_getpgid(posix_getpid()),
&#039;Process group id for Parent process&#039; =&gt; posix_getpgid(posix_getppid()),
&#039;Process group id of the session leader.&#039; =&gt; posix_getsid(posix_getpid()),
&#039;Info about a user by username&#039; =&gt; posix_getpwnam(get_current_user()),
&#039;Info about a user by user id&#039; =&gt; posix_getpwuid(posix_geteuid()),
&#039;Apache Version&#039; =&gt; (function_exists(&#039;apache_get_version&#039;)) ? print_r(apache_get_version(), 1) : &#039;&#039;,
&#039;Apache Modules&#039; =&gt; (function_exists(&#039;apache_get_modules&#039;)) ? print_r(apache_get_modules(), 1) : &#039;&#039;,
&#039;PHP_LOGO_GUI&#039; =&gt; php_logo_guid(),
&#039;ZEND_LOGO_GUI&#039; =&gt; zend_logo_guid()
);
&nbsp;
  foreach ($functions as $title =&gt; $v) $oa[$title] = $v;
&nbsp;
  return $oa;
}</pre>



<h3>get_debug_defined</h3>
<p>This gets all the defined constants, if verbose it gets more and gets the values for each.</p>

<pre>function get_debug_defined($vb=false)
{
  $oa=array();
  foreach ((array)@get_defined_constants() as $k =&gt; $v){if (!$vb &amp;&amp; in_array($k, array(&#039;ABSPATH&#039;, &#039;WP_ADMIN&#039;))) $vb = true;  if($vb)$oa[$k]=$v;}
&nbsp;
  foreach (
  array(&#039;WP_TEMP_DIR&#039;, &#039;WP_SITEURL&#039;, &#039;WP_HOME&#039;, &#039;ABSPATH&#039;, &#039;WP_CONTENT_URL&#039;,
  &#039;WP_CONTENT_DIR&#039;, &#039;WP_PLUGIN_DIR&#039;, &#039;WP_PLUGIN_URL&#039;, &#039;WP_LANG_DIR&#039;, &#039;TEMPLATEPATH&#039;,
  &#039;STYLESHEETPATH&#039;, &#039;WPINC&#039;, &#039;COOKIEPATH&#039;, &#039;SITECOOKIEPATH&#039;, &#039;ADMIN_COOKIE_PATH&#039;,
  &#039;PLUGINS_COOKIE_PATH&#039;, &#039;PHP_SAPI&#039;, &#039;PHP_OS&#039;, &#039;PHP_VERSION&#039;
  ) as $def) if (defined($def) &amp;&amp; $val = constant($def) &amp;&amp; !empty($val)) $oa[$def] = $val;
&nbsp;
  return $oa;
}</pre>


<h3>get_debug_inis</h3>
<p>This function gets the values of your php ini, if verbose it gets them all and shows the currently used value instead of both the global and local.</p>

<pre>function get_debug_inis($vb=false)
{
  $oa=array();
&nbsp;
  foreach (array(&#039;Error Log&#039; =&gt; &#039;error_log&#039;,
&#039;Session Data Path&#039; =&gt; &#039;session.save_path&#039;,
&#039;Upload Tmp Dir&#039; =&gt; &#039;upload_tm_p_dir&#039;,
&#039;Include Path&#039; =&gt; &#039;include_path&#039;,
&#039;Memory Limit&#039; =&gt; &#039;memory_limit&#039;,
&#039;Max Execution Time&#039; =&gt; &#039;max_execution_time&#039;,
&#039;Display Errors&#039; =&gt; &#039;display_errors&#039;,
&#039;Allow url fopen&#039; =&gt; &#039;allow_url_fopen&#039;,
&#039;Disabled Functions&#039; =&gt; &#039;disable_functions&#039;,
&#039;Safe Mode&#039; =&gt; &#039;safe_mode&#039;,
&#039;Open Basedir&#039; =&gt; &#039;open_basedir&#039;,
&#039;File Uploads&#039; =&gt; &#039;file_uploads&#039;,
&#039;Max Upload Filesize&#039; =&gt; &#039;upload_max_filesize&#039;,
&#039;Max POST Size&#039; =&gt; &#039;post_max_size&#039;,
&#039;Open Basedir&#039; =&gt; &#039;open_basedir&#039;) as $title =&gt; $ini_name) if (($val = &#039;&#039; &amp;&amp; $val = strval(ini_get($ini_name))) !== false &amp;&amp; !empty($val)) $oa[$title] = $val;
&nbsp;
  if($vb!==false){
    foreach ((array)@ini_get_all() as $k =&gt; $v) $oa[$k] = (($v[&#039;global_value&#039;] == $v[&#039;local_value&#039;]) ? $v[&#039;global_value&#039;] : $v);
  }
  return $oa;
}</pre>


<h3>get_debug_phpinfo</h3>
<p>I'm particularly proud of this function because the preg_replace was tough and the result is a perfect array of values returned by the phpinfo command.</p>

<pre>function get_debug_phpinfo()
{
  $oa=array();
  ob_start();
  phpinfo(-1);
  $oa = preg_replace(array(&#039;#^.*&lt;body&gt;(.*)&lt;/body&gt;.*$#ms&#039;, &#039;#&lt;h2&gt;PHP License&lt;/h2&gt;.*$#ms&#039;, &#039;#&lt;h1&gt;Configuration&lt;/h1&gt;#&#039;, "#\r?\n#", "#&lt;/(h1|h2|h3|tr)&gt;#", &#039;# +&lt;#&#039;, "#[ \t]+#", &#039;#&nbsp;#&#039;, &#039;#  +#&#039;, &#039;# class=".*?"#&#039;, &#039;%'%&#039;, &#039;#&lt;tr&gt;(?:.*?)" src="(?:.*?)=(.*?)" alt="PHP Logo" /&gt;&lt;/a&gt;&#039; . &#039;&lt;h1&gt;PHP Version (.*?)&lt;/h1&gt;(?:\n+?)&lt;/td&gt;&lt;/tr&gt;#&#039;,
    &#039;#&lt;h1&gt;&lt;a href="(?:.*?)?=(.*?)"&gt;PHP Credits&lt;/a&gt;&lt;/h1&gt;#&#039;, &#039;#&lt;tr&gt;(?:.*?)" src="(?:.*?)=(.*?)"(?:.*?)Zend Engine (.*?),(?:.*?)&lt;/tr&gt;#&#039;, "#  +#", &#039;#&lt;tr&gt;#&#039;, &#039;#&lt;/tr&gt;#&#039;), array(&#039;$1&#039;, &#039;&#039;, &#039;&#039;, &#039;&#039;, &#039;&lt;/$1&gt;&#039; . "\n", &#039;&lt;&#039;, &#039; &#039;, &#039; &#039;, &#039; &#039;, &#039;&#039;, &#039; &#039;, &#039;&lt;h2&gt;PHP Configuration&lt;/h2&gt;&#039; . "\n" . &#039;&lt;tr&gt;&lt;td&gt;PHP Version&lt;/td&gt;&lt;td&gt;$2&lt;/td&gt;&lt;/tr&gt;&#039; . "\n" . &#039;&lt;tr&gt;&lt;td&gt;PHP Egg&lt;/td&gt;&lt;td&gt;$1&lt;/td&gt;&lt;/tr&gt;&#039;,
    &#039;&lt;tr&gt;&lt;td&gt;PHP Credits Egg&lt;/td&gt;&lt;td&gt;$1&lt;/td&gt;&lt;/tr&gt;&#039;, &#039;&lt;tr&gt;&lt;td&gt;Zend Engine&lt;/td&gt;&lt;td&gt;$2&lt;/td&gt;&lt;/tr&gt;&#039; . "\n" . &#039;&lt;tr&gt;&lt;td&gt;Zend Egg&lt;/td&gt;&lt;td&gt;$1&lt;/td&gt;&lt;/tr&gt;&#039;, &#039; &#039;, &#039;%S%&#039;, &#039;%E%&#039;), ob_get_clean());
  $sections = explode(&#039;&lt;h2&gt;&#039;, strip_tags($oa, &#039;&lt;h2&gt;&lt;th&gt;&lt;td&gt;&#039;));
  unset($sections[0]);
  $oa = array();
  foreach ($sections as $section)
  {
    $n = substr($section, 0, strpos($section, &#039;&lt;/h2&gt;&#039;));
    preg_match_all(&#039;#%S%(?:&lt;td&gt;(.*?)&lt;/td&gt;)?(?:&lt;td&gt;(.*?)&lt;/td&gt;)?(?:&lt;td&gt;(.*?)&lt;/td&gt;)?%E%#&#039;, $section, $askapache, PREG_SET_ORDER);
    foreach ($askapache as $m) $oa[$n][$m[1]] = (!isset($m[3]) || $m[2] == $m[3]) ? $m[2] : array_slice($m, 2);
  }
  return $oa;
}</pre>




<h3>get_debug_included</h3>
<p>Gets a list of all the files included by php, if verbose it also super-stats them.</p>

<pre>function get_debug_included($vb=false)
{
  $oa=array();
  foreach((array)@get_included_files() as $k=&gt;$v) $oa[$v]=($vb===false) ? &#039;&#039; : $this-&gt;_stat($v);
  return $oa;
}</pre>








<h3>get_debug_classes</h3>
<p>Gets a list of predefined classes declared in your php instance, if verbose it gets EVERY class and also gets the methods for each.</p>

<pre>function get_debug_classes($vb=false)
{
  $classes=$oa=array();
  $classes= ($vb!==false) ? (array)@get_declared_classes() : array(&#039;WP&#039;,&#039;WP_Error&#039;,&#039;Walker&#039;,&#039;WP_Ajax_Response&#039;,&#039;wpdb&#039;,&#039;WP_Object_Cache&#039;,&#039;WP_Query&#039;,&#039;WP_Rewrite&#039;,&#039;WP_Locale&#039;);
  foreach ($classes as $k)  $oa[$k] = @get_class_methods($k);
&nbsp;
  return $oa;
}</pre>


<h3>get_debug_globals</h3>
<p>This function tries to get the values of every known (past and present) global variable in php.</p>

<pre>function get_debug_globals($vb=false)
{
  $oa=array();
&nbsp;
  $globs =
  array(
  &#039;GET&#039;     =&gt; isset( $_GET )?$_GET:&#039;&#039;,
  &#039;POST&#039;    =&gt; isset( $_POST )?$_POST:&#039;&#039;,
  &#039;COOKIE&#039;  =&gt; isset( $_COOKIE )?$_COOKIE:&#039;&#039;,
  &#039;SESSION&#039;   =&gt; isset( $_SESSION )?$_SESSION:&#039;&#039;,
  &#039;ENV&#039;     =&gt; isset( $_ENV )?$_ENV:&#039;&#039;,
  &#039;FILES&#039;     =&gt; isset( $_FILES )?$_FILES:&#039;&#039;,
  &#039;SERVER&#039;  =&gt; isset( $_SERVER )?$_SERVER:&#039;&#039;,
  &#039;SERVER&#039;  =&gt; isset( $_SERVER )?$_SERVER:&#039;&#039;,
  &#039;UPLOAD&#039;  =&gt; function_exists(&#039;wp_upload_dir&#039;) ? wp_upload_dir():&#039;&#039;,
  &#039;REQUEST&#039;   =&gt; isset( $_REQUEST )?$_REQUEST:&#039;&#039;,
  &#039;HTTP_POST_FILES&#039;   =&gt; isset( $HTTP_POST_FILES )?$HTTP_POST_FILES:&#039;&#039;,
  &#039;HTTP_POST_VARS&#039;    =&gt; isset( $HTTP_POST_VARS )?$HTTP_POST_VARS:&#039;&#039;,
  &#039;HTTP_SERVER_VARS&#039;  =&gt;  isset( $HTTP_SERVER_VARS )?$HTTP_SERVER_VARS:&#039;&#039;,
  &#039;HTTP_RAW_POST_DATA&#039; =&gt; isset( $HTTP_RAW_POST_DATA )?$HTTP_RAW_POST_DATA:&#039;&#039;,
  &#039;HTTP_GET_VARS&#039;     =&gt; isset( $HTTP_GET_VARS )?$HTTP_GET_VARS:&#039;&#039;,
  &#039;HTTP_COOKIE_VARS&#039;  =&gt;  isset( $HTTP_COOKIE_VARS )?$HTTP_COOKIE_VARS:&#039;&#039;,
  &#039;HTTP_ENV_VARS&#039;     =&gt; isset( $HTTP_ENV_VARS )?$HTTP_ENV_VARS:&#039;&#039;,
  );
  foreach ($globs as $k =&gt; $v) if (isset($v) &amp;&amp; sizeof($v) &gt; 0) $oa[$k] = $v;
&nbsp;
  foreach (array_keys($_SERVER) as $k) if ($val = strval($_SERVER[$k]) &amp;&amp; !empty($val)) $oa[(substr($k, 0, 5) == &#039;HTTP_&#039; ? &#039;HTTP&#039; : &#039;SERVER&#039;)][$k] = $_SERVER[$k];
&nbsp;
  return $oa;
}</pre>


<h3>get_debug_loaded_extensions</h3>
<p>Returns a list of all the loaded extensions in php.  If verbose it also returns their functions!</p>

<pre>function get_debug_loaded_extensions($vb=false)
{
  $oa=array();
  foreach((array)@get_loaded_extensions() as $k=&gt;$v) $oa[$v]= ($vb===false) ? &#039;&#039; : (array)@get_extension_funcs($v);
  return $oa;
}</pre><p><a href="http://www.askapache.com/wordpress/debug-viewer-plugin.html"></a><a href="http://www.askapache.com/wordpress/debug-viewer-plugin.html">AskApache Debug Viewer Plugin for WordPress</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/wordpress/debug-viewer-plugin.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Password Protection Plugin Status</title>
		<link>http://www.askapache.com/wordpress/password-protection-plugin-status.html</link>
		<comments>http://www.askapache.com/wordpress/password-protection-plugin-status.html#comments</comments>
		<pubDate>Sun, 01 Mar 2009 18:39:57 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=1966</guid>
		<description><![CDATA[<p><strong>Enumerating Permissions can be Annoying</strong></p>
<p>Don’t ask me how because I won’t tell you, but on one of the hosts I was testing on that did not allow direct access I was able to get the Apache server running as dhapache to erroneously write a file into my users blog directory. This is a <strong>big security no-no</strong> and I now have my .htaccess file written into the blog directory where it should go, but instead of my php script’s user having write access to the file so I can modify it, its owned by dhapache! Because the file is owned by dhapache I shouldn’t even be allowed to know it exists, but there it is. So the next step was to try and take ownership of the .htaccess file so that I could modify it. I tried and tried but was unsuccessful, I couldn’t modify it so that was another dead end.  Actually it took me awhile to figure out how to remove the file from my directory. Being that it was owned by dhapache I couldn’t delete or modify it using my php process or even through ftp/ssh! Sysadmins regularly run find commands that search the servers for any files owned by <strong>dhapache</strong> that should not be there as this is a big red flag that someone has found a way to manipulate dhapache which could potentially lead to modifying dhapache-owned server config files, which sometimes is all it takes to hack your website and server..  Luckily I was able to delete it by basically running the hack again to overwrite the file.</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/wordpress/password-protection-plugin-status.html"></a><a href="http://www.askapache.com/wordpress/password-protection-plugin-status.html"><cite>AskApache.com</cite></a></p><p>I wanted to address why the update to the AskApache Password Protection plugin didn't happen pre-2009 as I had hoped.. Mostly due to my job but I thought I could at least fill you in.  Oh and this is going to get very boring very fast, unless you're ready to rumble in the zone.</p>

<h2>File Permissions!</h2>
The main issue with the password protection plugin working for some people and not others is due to <a title="detailed file permission article" href="http://www.askapache.com/security/chmod-stat.html">file permission configurations</a>.  WordPress is simply a group of .php files saved on your server.  The actual program that is in fact running WordPress is the <a title="SuEXEC and php.cgi" href="http://www.askapache.com/htaccess/php-cgi-redirect_status.html">PHP interpreter</a>, which is in turn controlled by the Apache Server.  Almost all computers are running at least 2 servers, the Web Server which serves and displays your files, and a FTP server.


<p><a class="IFL" href="http://uploads.askapache.com/2009/03/apache-security-model-tall1.png"><img src="http://uploads.askapache.com/2009/03/apache-security-model-tall1-250x123.png" alt="Apache Security Model - In Color" title="apache-security-model-wide" width="250" height="123" /></a>  Here's a detailed look at the Apache Security Model, from <a href="http://www.apachesecurity.net/blog/2009/02/apache_security_model.html">ApacheSecurity.net</a>, a blog maintained by <em>Ivan Ristic</em>, the author of <a href="http://www.modsecurity.org/">ModSecurity</a>.<br class="C" /></p>

<p>The problem is happening because when you login to your FTP server with your username and password, the files that you upload are then  owned by that username and password, which is almost always an actual user account on the server system.  But the Apache Server is an executable file itself, and it is not owned by your FTP username, for security reasons.  Apache controls the PHP Interpreter, which parses and executes the WordPress and plugin files as a separate user.  ( <a href="http://httpd.apache.org/docs/trunk/suexec.html">SuEXEC</a>, <a href="http://httpd.apache.org/docs/trunk/misc/security_tips.html">Apache Security Tips</a> ) </p>

So what happens is the <code>askapache-password-protect.php</code> file saved on your server and is owned by the user that created it (if you downloaded it to your computer then used ftp to transfer, your ftp user owns it..  if you used a php downloader script, then the php process owner owns it)   So when you click on the Run Tests button from the WordPress administration website what you are doing is sending a request via HTTP to your Apache Server process, which sees the requested file is .php so it then runs the php interpreter to execute the askapache-password-protect.php file, then that file uses programming to attempt and write/modify a file in your blog's root directory.

<h2>Process Owner vs. File Owner</h2>
So who owns your blog's root directory?  Your ftp user account/ you do..   but who owns the process that is trying to write/modify a file that is owned by your ftp user?  The PHP Process that is actually executing the file access/write requests.  This is the core way that 99% of all web sites get cracked into.. All these malicious robots and exploit bots do is attempt to write a file onto your server so that it can then be used to take over your site.  If they can save a file on your blog's directory (uploads, insecure plugin code, not filtering user input, etc..) it inherits the permissions of the process that actually wrote the data bits onto the hard-drive.

So some server-admins/web hosts configure the php interpreter to not have write access anywhere except for a couple neccessary locations like /tmp.  They have auto-installation's available through their online web panels, meaning instead of executing .php scripts in your user directory as the php process they force you to use, they can bypass all that because the installation scripts they use are all on their systems, not on your "locked-down" cluster.

This is the fundamental security battle that network server security is all based on..   Apache is owned by a powerful user because it owns the server process, so apache is often run as the user dhapache or nobody..  If a cracker is able to find a way to get a file saved on your server with the dhapache user as the owner then they've basically just gotten control of the whole thing.  When you upload a file to your server using the add attachment form in wordpress, the file first goes through the dhapache user which passes the file to the php process owner which has much less permissions.  Apache has been in open-source development for many many years now, its the safest most secure server in the world, windows servers are hackable, apache servers are hacked usually only when the sysadmin configures it wrong or accidentally.

Believe it or not, as confusing as my feeble explanation was, this is only like .1% of whats going on.. I've basically spent the last several months developing the new version specifically to be able to work no matter what configuration you have.  What I ended up doing was finding ways to bypass this security on a couple hosting providers that are setup in this way, but even though I got it to work in most instances it basically was hacking their systems, and if I published that code to automatically bypass web-hosts security setups I think I'd be in big trouble and they would just close those specific holes and the plugin would not work again.   So I decided instead of exploiting host-specifics hacks to get the plugin to work that I would focus on the method that WordPress sorta uses.  The code they have now (2.8 bleeding-edge) still isn't where it needs to be, but this is some difficult stuff and they have a brilliant start, it'll work.. just a question of when.

<h2><code>wp-admin/includes/file.php</code></h2>
<p>Ok so this function <code>get_filesystem_method</code> is a brilliant bit of code that would've been beyond my current PHP skills to come up with.  It determines which if any of the following methods can be used to modify files on your server from within WordPress, which is exactly what the new version of the passpro plugin needs to use.   The first test simply creates a file from within php using wp_tempnam, a function that attempts to locate and write to a temporary location on your server that has the best chance of having write access.  If it is successfully created (this code assumes that it will be, something they need to fix) then the fileowner (uses stat internally) of the temp file just created is compared to the owner of the php script...  Normally this works and then the plugin woks too, but on some hosts the script is running as a separate user than that of the file which means you can't directly access the local file system.  That is what is occurring for most of you who experience permission problems while testing the plugin.  There are thousands of caveats for each little part depending on your php version, php setup, server setup, server version, which Server API you are using, the type of SAPI being used, and on and on..</p>
<pre>function get_filesystem_method($args = array()) {
  $method = false;
  if( function_exists(&#039;getmyuid&#039;) &amp;&amp; function_exists(&#039;fileowner&#039;) ){
    $temp_file = wp_tempnam();
    if ( getmyuid() == fileowner($temp_file) ) $method = &#039;direct&#039;;
    unlink($temp_file);
  }
  if ( ! $method &amp;&amp; isset($args[&#039;connection_type&#039;]) &amp;&amp; &#039;ssh&#039; == $args[&#039;connection_type&#039;] &amp;&amp; extension_loaded(&#039;ssh2&#039;) )
          $method = &#039;ssh2&#039;;
  if ( ! $method &amp;&amp; extension_loaded(&#039;ftp&#039;) )
          $method = &#039;ftpext&#039;;
  if ( ! $method &amp;&amp; ( extension_loaded(&#039;sockets&#039;) || function_exists(&#039;fsockopen&#039;) ) )
          $method = &#039;ftpsockets&#039;; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
  return apply_filters(&#039;filesystem_method&#039;, $method);
}</pre>


<h2>Enumerating Permissions can be Annoying</h2>
<p>This was part of some tests I did to see what kind of access I had with the very helpful posix functions which are very accurate as well since they were designed for a system with file permissions, ie. not Win.  Don't ask me how because I won't tell you, but on one of the hosts I was testing on that did not allow direct access I was able to get the Apache server running as dhapache to erroneously write a file into my users blog directory.  This is a big security no-no and I now have my .htaccess file written into the blog directory where it should go, but instead of my php script's user having write access to the file so I can modify it, its owned by dhapache!  Because the file is owned by dhapache I shouldn't even be allowed to know it exists, but there it is.  So the next step was to try and take ownership of the .htaccess file so that I could modify it.  I tried and tried but was unsuccessful, I couldn't modify it so that was another dead end.  Actually it took me awhile to figure out how to remove the file from my directory.  Being that it was owned by dhapache I couldn't delete or modify it using my php process or even through ftp/ssh!  Sysadmins regularly run find commands that search the servers for any files owned by dhapache that should not be there as this is a big red flag that someone has found a way to manipulate dhapache which could potentially lead to modifying dhapche-owned server config files.. Luckily I was able to delete it by basically running the hack again to overwrite the file.</p>
<pre>  if ((posix_setgid(getmygid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETGID of {$file}  to " . getmygid(), 3);
  elseif ((posix_setgid(filegroup(__file__))) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETUID of {$file} to " . filegroup(__file__), 3);
  if ((posix_setegid(getmygid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETEGID of {$file} to " . getmygid(), 3);
  elseif ((posix_setegid(filegroup(__file__))) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETEGID of {$file} to " . filegroup(__file__), 3);
  if ((posix_setuid(getmyuid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETUID of {$file}  to " . getmyuid(), 3);
  elseif ((posix_setuid(get_current_user())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETUID of {$file} to " . get_current_user(), 3);
  if ((posix_seteuid(getmyuid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETEUID of {$file} to " . getmyuid(), 3);
  elseif ((posix_seteuid(get_current_user())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing SETEUID of {$file} to " . get_current_user(), 3);
  if ((chmod($file, FS_CHMOD_DIR) || chmod($file, 0776) || chmod($file, 0766) || chmod($file,
    FS_CHMOD_FILE)) !== false) $this-&gt;to_log(&#039;&#039;, 1, "Success Changing Mode of {$file}", 3);
  if ((chown($file, getmyuid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Ownership of {$file} to " . getmyuid(), 3);
  elseif ((chown($file, get_current_user())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Ownership of {$file} to " . get_current_user(), 3);
  if ((chgrp($file, getmygid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Group of {$file} to " . getmygid(), 3);
  elseif ((chgrp($file, filegroup(__file__))) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Group of {$file} to " . filegroup(__file__), 3);
  if ((chmod($file, FS_CHMOD_DIR) || chmod($file, 0776) || chmod($file, 0766) || chmod($file,
    FS_CHMOD_FILE)) !== false) $this-&gt;to_log(&#039;&#039;, 1, "Success Changing Mode of {$file}", 3);
  if ((chown($file, getmyuid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Ownership of {$file} to " . getmyuid(), 3);
  elseif ((chown($file, get_current_user())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Ownership of {$file} to " . get_current_user(), 3);
  if ((chgrp($file, getmygid())) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Group of {$file} to " . getmygid(), 3);
  elseif ((chgrp($file, filegroup(__file__))) !== false) $this-&gt;to_log(&#039;&#039;, 1,
      "Success Changing Group of {$file} to " . filegroup(__file__), 3);
  return (!$this-&gt;_fclose($fh)) ? $this-&gt;to_log(__function__ . &#039;:&#039; . __line__ .
    " Error closing {$mode} handle for {$file}", 0) : $total;</pre>

If php process isn't allowed to write to your web directory but you have an ftp account that is, then we request your ftp username/password in wordpress and if the php process running the <code>askapache-password-protect.php</code> plugin script is allowed access to <a href="http://www.askapache.com/php/fsockopen-socket.html">raw networking sockets using fsockopen</a> then we can basically access and write to your blog's <code>.htaccess</code> file by using php to mimick an ftp client session. There are also other protocols and options available using php if ftp/fsockopen isn't allowed, but you run out of alternatives quick.  Using the curl extension is one option.

So I wrote my own ftp library for a fsockopen class I had already developed for specific test requirements in unreleased versions, so the release of the new askapache password protect plugin will work for 75% or so of the people who have trouble now.. not to mention the insane logging and debugging I've added while looking for the reasons some web-hosts still don't work.  Some use custom php security modules, wrappers, and custom virtual servers that are akin to a vmware server.  So for maybe 10% of those running apache who have had problems they would still have them. I'm still playing with some ssh capability from within the plugin similar to the ftp technique..  I really hope WordPress just adds this functionality by updating their current filesystem classes..


<h2>Fsockopen Payload Class</h2>
<p>Here's what I had several versions ago.. Just sticking it up here in case anyone is curious, one cool thing this version starts to incorporate is being able to send direct data payloads across the socket so it can be used like <a href="http://metasploit.com/" title="Metasploit provides useful information to people who perform penetration testing, IDS signature development, and exploit research.">the metasploit framework</a> to send payloads of exploits, but of course we're using it to mimick other protocols like ftp, which can be setup by feeding hex into the socket direct from a real ftp client, and piping the output. Keep in mind that this is my first time using php classes, so the learning curve has been incredible...</p>
<pre>&lt;?php
error_log("RUNNING " . basename(__file__) . "\n");
if (!in_array(&#039;AskApache_Net&#039;, get_declared_classes()) &amp;&amp; !class_exists(&#039;AskApache_Net&#039;)):
 class AskApache_Net extends AskApachePassPro
 {
  var $_fp = null;
  var $_socket = array(&#039;protocol&#039; =&gt; &#039;1.0&#039;, &#039;method&#039; =&gt; &#039;GET&#039;, &#039;referer&#039; =&gt;
   &#039;http://www.askapache.com/&#039;, &#039;port&#039; =&gt; &#039;80&#039;, &#039;ua&#039; =&gt;
   &#039;Mozilla/5.0 (compatible; AskApache_Net/1.6; http://www.askapache.com/)&#039;, &#039;scheme&#039; =&gt;
   &#039;http&#039;, &#039;transport&#039; =&gt; &#039;&#039;, &#039;host&#039; =&gt; &#039;&#039;, &#039;user&#039; =&gt; &#039;&#039;, &#039;pass&#039; =&gt; &#039;&#039;, &#039;path&#039; =&gt; &#039;/&#039;,
   &#039;query&#039; =&gt; &#039;&#039;, &#039;fragment&#039; =&gt; &#039;&#039;);
  var $authtype = &#039;Basic&#039;;
  var $timeout = 15;
  var $_dh = &#039;&#039;;
  var $_digest = array(&#039;realm&#039; =&gt; &#039;&#039;, &#039;nonce&#039; =&gt; &#039;&#039;, &#039;uri&#039; =&gt; &#039;&#039;, &#039;algorithm&#039; =&gt; &#039;MD5&#039;,
   &#039;qop&#039; =&gt; &#039;auth&#039;, &#039;opaque&#039; =&gt; &#039;&#039;, &#039;domain&#039; =&gt; &#039;&#039;, &#039;nc&#039; =&gt; &#039;00000001&#039;, &#039;cnonce&#039; =&gt;
   &#039;82d057852a9dc497&#039;, &#039;A1&#039; =&gt; &#039;&#039;, &#039;A2&#039; =&gt; &#039;&#039;, &#039;response&#039; =&gt; &#039;&#039;);
  var $_ACLF = "\r\n";
  var $_request_body = &#039;&#039;;
  var $_request_headers = array();
  var $_response_headers = array();
  var $my_headers;
  var $_response_header = &#039;&#039;;
  var $_response_protocol = &#039;&#039;;
  var $_response_version = &#039;&#039;;
  var $_response_code = &#039;&#039;;
  var $_response_message = &#039;&#039;;
  var $_response_body = &#039;&#039;;
  var $_errs = array(3 =&gt; &#039;Socket creation failed&#039;, 4 =&gt; &#039;DNS lookup failure&#039;, 5 =&gt;
   &#039;Connection refused or timed out&#039;, 111 =&gt; &#039;Connection refused&#039;, 113 =&gt;
   &#039;No route to host&#039;, 110 =&gt; &#039;Connection timed out&#039;, 104 =&gt; &#039;Connection reset by client&#039;);
&nbsp;
  /**
   * AskApache_Net::AskApache_Net()
   */
  function AskApache_Net()
  {
   return $this-&gt;__construct();
  }
&nbsp;
  /**
   * AskApache_Net::__destruct()
   */
  function __destruct()
  {
   $this-&gt;_timer(&#039;class&#039;);
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::__construct()
   */
  function __construct()
  {
   $this-&gt;_timer(&#039;class&#039;);
   $this-&gt;_ACLF = chr(13) . chr(10);
   @set_time_limit(60);
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::hsockit()
   */
  function hsockit($URI)
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   $this-&gt;_socket[&#039;method&#039;] = &#039;HEAD&#039;;
   return $this-&gt;sockit($URI);
  }
&nbsp;
  /**
   * AskApache_Net::sockit()
   */
  function sockit($URI = &#039;&#039;)
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if (!$this-&gt;_build_sock($URI)) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__,
     "Failed!", 0);
   if (!$this-&gt;_connect()) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__, "Failed!", 0);
   $this-&gt;_build_request();
   if (!$this-&gt;_build_request()) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__,
     "Failed!", 0);
   if (!$this-&gt;_tx()) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__, "tx Failed!", 0);
   if (!$this-&gt;_rx()) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__, "rx Failed!", 0);
   if (!$this-&gt;_disconnect()) return $this-&gt;msg(__function__ . &#039;:&#039; . __line__,
     "disconnect Failed!", 0);
   if ((bool)$this-&gt;net_debug === true) {
    foreach (array(&#039;out_payload&#039;, &#039;_request_body&#039;, &#039;_response_header&#039;, &#039;_response_body&#039;) as
     $nam) {
     if (is_array($this-&gt;$nam)) {
      if (sizeof($this-&gt;$nam) &gt; 1) {
       echo "\n\n{$nam}\n";
       print_r($this-&gt;$nam);
      }
     } else {
&nbsp;
      if (!empty($this-&gt;$nam)) {
       echo "\n\n{$nam}\n";
       echo $this-&gt;$nam;
      }
     }
    }
    $this-&gt;tcp_trace(1);
   }
   return (int)$this-&gt;_response_code;
  }
&nbsp;
  /**
   * AskApache_Net::_build_sock()
   */
  function _build_sock($url)
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   $socket_info = &amp;$this-&gt;_socket;
   if (!$u_bits = parse_url($url)) return false;
   if (empty($u_bits[&#039;method&#039;])) $u_bits[&#039;method&#039;] = &#039;GET&#039;;
   if (empty($u_bits[&#039;protocol&#039;])) $u_bits[&#039;protocol&#039;] = &#039;1.0&#039;;
   if (empty($u_bits[&#039;host&#039;])) $u_bits[&#039;host&#039;] = $_SERVER[&#039;HTTP_HOST&#039;];
   if (empty($u_bits[&#039;scheme&#039;])) $u_bits[&#039;scheme&#039;] = &#039;http&#039;;
   if (empty($u_bits[&#039;port&#039;])) $u_bits[&#039;port&#039;] = $_SERVER[&#039;SERVER_PORT&#039;];
   $u_bits[&#039;path&#039;] = (empty($u_bits[&#039;path&#039;]) ? &#039;/&#039; : $u_bits[&#039;path&#039;]) . (!empty($u_bits[&#039;query&#039;]) ?
    &#039;?&#039; . $u_bits[&#039;query&#039;] : &#039;&#039;);
   if (empty($u_bits[&#039;ua&#039;])) $u_bits[&#039;ua&#039;] =
     &#039;Mozilla/5.0 (compatible; AskApache_Net/1.0; http://www.askapache.com)&#039;;
   if (empty($u_bits[&#039;referer&#039;])) $u_bits[&#039;referer&#039;] = &#039;http://www.askapache.com&#039;;
   if (empty($u_bits[&#039;fragment&#039;])) unset($u_bits[&#039;fragment&#039;]);
   if (empty($u_bits[&#039;user&#039;])) unset($u_bits[&#039;user&#039;]);
   if (empty($u_bits[&#039;pass&#039;])) unset($u_bits[&#039;pass&#039;]);
   if ($u_bits[&#039;scheme&#039;] == &#039;https&#039; || $this-&gt;_socket[&#039;scheme&#039;] == &#039;https&#039;) $u_bits[&#039;transport&#039;] =
     &#039;ssl://&#039;;
   if ($u_bits[&#039;scheme&#039;] == &#039;https&#039; || $this-&gt;_socket[&#039;scheme&#039;] == &#039;https&#039;) $u_bits[&#039;port&#039;] =
     &#039;443&#039;;
   $socket_info = $this-&gt;_parse_args($u_bits, $socket_info);
   extract($socket_info, EXTR_SKIP);
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::_build_auth_header()
   */
  function _build_auth_header()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if ($this-&gt;authtype == &#039;Basic&#039;) $this-&gt;_request_headers[] = &#039;Authorization: Basic &#039; .
     base64_encode($this-&gt;_socket[&#039;user&#039;] . ":" . $this-&gt;_socket[&#039;pass&#039;]);
   elseif ($this-&gt;authtype == &#039;Digest&#039;) {
    $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
    $this-&gt;_socket[&#039;protocol&#039;] = &#039;1.1&#039;;
    $hdr = $mtx = array();
    preg_match_all(&#039;/(\w+)=(?:"([^"]+)"|([^\s,]+))/&#039;, $this-&gt;_dh, $mtx, PREG_SET_ORDER);
    foreach ($mtx as $m) $hdr[$m[1]] = $m[2] ? $m[2] : $m[3];
    foreach ($hdr as $key =&gt; $val)
     if (array_key_exists($key, $this-&gt;_digest) &amp;&amp; !empty($val)) $this-&gt;_digest[$key] = $val;
    $this-&gt;_digest[&#039;uri&#039;] = $this-&gt;_socket[&#039;path&#039;];
    $this-&gt;_digest[&#039;A1&#039;] = md5($this-&gt;_socket[&#039;user&#039;] . &#039;:&#039; . $this-&gt;_digest[&#039;realm&#039;] .
     &#039;:&#039; . $this-&gt;_socket[&#039;pass&#039;]);
    $this-&gt;_digest[&#039;A2&#039;] = md5($this-&gt;_socket[&#039;method&#039;] . &#039;:&#039; . $this-&gt;_socket[&#039;path&#039;]);
    $this-&gt;_digest[&#039;response&#039;] = md5($this-&gt;_digest[&#039;A1&#039;] . &#039;:&#039; . $this-&gt;_digest[&#039;nonce&#039;] .
     &#039;:&#039; . $this-&gt;_digest[&#039;nc&#039;] . &#039;:&#039; . $this-&gt;_digest[&#039;cnonce&#039;] . &#039;:&#039; . $this-&gt;_digest[&#039;qop&#039;] .
     &#039;:&#039; . $this-&gt;_digest[&#039;A2&#039;]);
    $this-&gt;_request_headers[] = sprintf(&#039;Authorization: Digest username="%1$s", realm="%2$s", nonce="%3$s",&#039;.
     &#039;uri="%4$s", algorithm=%5$s, response="%6$s", qop="%7$s", nc="%8$s"%9$s%10$s&#039;,
     $this-&gt;_socket[&#039;user&#039;], $this-&gt;_digest[&#039;realm&#039;], $this-&gt;_digest[&#039;nonce&#039;], $this-&gt;
     _digest[&#039;uri&#039;], $this-&gt;_digest[&#039;algorithm&#039;], $this-&gt;_digest[&#039;response&#039;], $this-&gt;
     _digest[&#039;qop&#039;], $this-&gt;_digest[&#039;nc&#039;], !empty($this-&gt;_digest[&#039;cnonce&#039;]) ? &#039;, cnonce="&#039; .
     $this-&gt;_digest[&#039;cnonce&#039;] . &#039;"&#039; : &#039;&#039;, !empty($this-&gt;_digest[&#039;opaque&#039;]) ? &#039;, opaque="&#039; .
     $this-&gt;_digest[&#039;opaque&#039;] . &#039;"&#039; : &#039;&#039;);
   }
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::_build_request()
   */
  function _build_request()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   $this-&gt;_request_headers[] = $this-&gt;_socket[&#039;method&#039;] . " " . $this-&gt;_socket[&#039;path&#039;] .
    " HTTP/" . $this-&gt;_socket[&#039;protocol&#039;];
   if (is_array($this-&gt;my_headers) &amp;&amp; sizeof($this-&gt;my_headers) &gt; 0) $this-&gt;
     _request_headers = array_merge($this-&gt;_request_headers, $this-&gt;my_headers);
   else {
    $this-&gt;_request_headers[] = "Host: " . $this-&gt;_socket[&#039;host&#039;];
    $this-&gt;_request_headers[] = "User-Agent: " . $this-&gt;_socket[&#039;ua&#039;];
    $this-&gt;_request_headers[] = &#039;Accept: application/xhtml+xml,text/html;q=0.9,*/*;q=0.5&#039;;
    $this-&gt;_request_headers[] = &#039;Accept-Language: en-us,en;q=0.5&#039;;
    $this-&gt;_request_headers[] = &#039;Accept-Encoding: none&#039;;
    $this-&gt;_request_headers[] = &#039;Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7&#039;;
    $this-&gt;_request_headers[] = &#039;Referer: &#039; . $this-&gt;_socket[&#039;referer&#039;];
   }
   if (!empty($this-&gt;_socket[&#039;user&#039;]) &amp;&amp; !empty($this-&gt;_socket[&#039;pass&#039;])) $this-&gt;
     _build_auth_header();
   if ($this-&gt;out_payload !== false) $this-&gt;_request_body = $this-&gt;out_payload;
   else  $this-&gt;_request_body = join($this-&gt;_ACLF, $this-&gt;_request_headers) . $this-&gt;
     _ACLF . $this-&gt;_ACLF;
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::_tx()
   */
  function _tx()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   return (bool)(is_resource($this-&gt;_fp) &amp;&amp; $this-&gt;_netwrite($this-&gt;_fp, $this-&gt;
    _request_body));
  }
&nbsp;
  /**
   * AskApache_Net::_rx()
   */
  function _rx()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if (!is_resource($this-&gt;_fp)) return false;
   $this-&gt;_response = $this-&gt;_netread($this-&gt;_fp, 500000);
   $parts = explode($this-&gt;_ACLF . $this-&gt;_ACLF, ltrim($this-&gt;_response), 2);
   $this-&gt;_response_header = trim($parts[0]);
   $this-&gt;_response_body = trim($parts[1]);
   if (preg_match(&#039;#([^/]*)/([\d\.]+) ([\d]*?) (.*)#&#039;, $this-&gt;_response_header, $htx)) {
    $this-&gt;_response_protocol = trim($htx[1]);
    $this-&gt;_response_version = trim($htx[2]);
    $this-&gt;_response_code = trim($htx[3]);
    $this-&gt;_response_message = trim($htx[4]);
   }
   if (preg_match_all(&#039;#([^:]+)\:?(.*)#&#039;, str_replace($htx, &#039;&#039;, $this-&gt;_response_header),
    $mtx, PREG_SET_ORDER)) {
    foreach ($mtx as $m) {
     $this-&gt;_headers[strtolower(trim($m[1]))] = trim($m[2]);
     if (preg_match(&#039;/(WWW|Proxy)-Authenticate:.*Digest/i&#039;, trim($m[1]))) $this-&gt;_dh =
       trim($m[1]);
    }
   }
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::tcp_trace()
   */
  function tcp_trace($p = false)
  {
   $this-&gt;_timer(__function__ );
   $ret = join("\n", array_merge((array )$this-&gt;_request_headers, array(&#039;&#039;), (array )$this-&gt;
    _response_headers));
   if ($p !== false) {
    echo $ret;
    $ret = true;
   }
   $this-&gt;_timer(__function__ );
   return $ret;
  }
&nbsp;
  /**
   * AskApache_Net::_get_ip()
   */
  function _get_ip($host)
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
&nbsp;
   if (!preg_match(&#039;/^[\t ]*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[\t ]*$/&#039;, $host)) $hostip =
     gethostbyname($host);
   $ip = ($hostip == $host) ? $host : long2ip(ip2long($hostip));
   return $ip;
  }
&nbsp;
  /**
   * AskApache_Net::_connect()
   */
  function _connect()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if (false === ($this-&gt;_fp = fsockopen($this-&gt;_get_ip($this-&gt;_socket[&#039;host&#039;]), $this-&gt;
    _socket[&#039;port&#039;], $errno, $errstr, $this-&gt;timeout)) || !is_resource($this-&gt;_fp)) {
    $err = (array_key_exists($errno, $this-&gt;_errs)) ? $this-&gt;_errs[$errno] :
     &#039;Connection failed&#039;;
    return $this-&gt;msg(__function__ . &#039;:&#039; . __line__ . " Fsockopen failed! [{$errno}] {$err} ({$errstr})",
     0);
   }
   if (function_exists("socket_set_timeout")) socket_set_timeout($this-&gt;_fp, $this-&gt;
     timeout);
   elseif (function_exists("stream_set_timeout")) stream_set_timeout($this-&gt;_fp, $this-&gt;
     timeout);
   usleep(10000);
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::_disconnect()
   */
  function _disconnect()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if (is_resource($this-&gt;_fp)) return $this-&gt;_fclose($this-&gt;_fp);
   else  $this-&gt;_fp = null;
   return true;
  }
&nbsp;
  /**
   * AskApache_Net::get_response_headers()
   */
  function get_response_headers($header = false)
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   if ($header !== false &amp;&amp; array_key_exists($header, $this-&gt;_response_headers)) return $this-&gt;
     _response_headers[$header];
   return $this-&gt;_response_headers;
  }
&nbsp;
  /**
   * AskApache_Net::get_response_body()
   */
  function get_response_body()
  {
   $this-&gt;msg(__function__ . &#039;:&#039; . __line__, 3);
   return $this-&gt;_response_body;
  }
&nbsp;
  /**
   * AskApache_Net::_netread()
   */
  function _netread(&amp;$fh, $ts = 50000000, $bs = 124)
  {
   $this-&gt;_timer(__function__ );
   for ($d = $b = &#039;&#039;, $rt = $at = $r = 0; ($fh !== false &amp;&amp; !feof($fh) &amp;&amp; $b !== false &amp;&amp;
    $at &lt; 50000000 &amp;&amp; $rt &lt; $ts); $r = $ts - $rt, $bs = (($bs &gt; $r) ? $r : $bs), $this-&gt;
    _timer("R: {$rt}"), $b = fread($fh, $bs), $br = strlen($b), $d .= $b, $this-&gt;_timer("R: {$rt}"),
    $rt += $br, $at++, $this-&gt;msg("[RT: {$rt}]\t[BR: {$br}" . (($ts != 50000000) ? "]\t\t [{$r} / {$ts}]" :
    " : {$bs}]\t[{$at}]"))) ;
   $this-&gt;_timer(__function__ );
   return ((strlen($d) != 0)) ? $d : false;
  }
&nbsp;
  /**
   * AskApache_Net::_netwrite()
   */
  function _netwrite(&amp;$fh, $d = &#039;&#039;, $bs = 512)
  {
   $this-&gt;_timer(__function__ );
&nbsp;
   for ($bw = $wt = $at = 0, $dat = &#039;&#039;, $ts = strlen($d); ($fh !== false &amp;&amp; $bw !== false &amp;&amp;
    $at &lt; 50000000 &amp;&amp; $wt &lt; $ts); $r = $ts - $wt, $bs = (($bs &gt; $r) ? $r : $bs), $dat =
    substr($d, $wt, $bs), $bw = fwrite($fh, $dat), $wt += $bw, $this-&gt;msg("[WT: {$wt}]\t[BW: {$bw}]\t\t[I: {$r} / {$ts}:{$bs}] - {$at}"),
    $at++) ;
   $this-&gt;msg("[WT: {$wt}]\t[BW: {$bw}]\t\t[I: {$r} / {$ts}:{$bs}] - {$at}");
   $this-&gt;_timer(__function__ );
   return ($wt == $ts) ? true : false;
  }
 }
endif;
?&gt;</pre>




So I decided to finally give in to what I've been avoiding all along and added a php-software-based method that will work on everycomputer, windows, blackberrys, etc.. That took me about 15minutes as its just a few lines of code.. The problem I have with it is that php is what is actually controlling the sending, receiving, and verifying of the authentication headers instead of using the builtin super-secure apache method.

Here's how you would block someone using the apache/askapache way:
<pre>[Exploit Request] =&gt; ([BLOCKED]-AskApache)</pre>
This prevents the exploit from even reaching PHP, saving your computer a lot of CPU/memory and bandwdith, and obviously can't exploit wordpress if php isn't even loading.

Here's how the php-software-based method blocks the same request:
<pre>[Exploit Request] =&gt; (AskApache) =&gt; (PHP) =&gt; (WordPress) =&gt; ([BLOCKED]-askapache-password-protect.php)</pre>

So the last bit of programming and research I'm doing at the moment is how to cause the askapache-password-protect plugin to execute as soon as possible, ideally it would execute before WordPress starts..   And I am still crazy swamped at work, this was the longest non-posting period of the blog to date!<p><a href="http://www.askapache.com/wordpress/password-protection-plugin-status.html"></a><a href="http://www.askapache.com/wordpress/password-protection-plugin-status.html">Password Protection Plugin Status</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/wordpress/password-protection-plugin-status.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

