Loading/Unloading a registry hive programmatically in Delphi 5+

Concepts demonstrated:
Registry Use (See procedure TfrmLoadHive.btnDisplayValueClick(Sender: TObject))
Hives & The Default User hive & .Default (See below)
Executing another program from within a Delphi program (See procedure TfrmLoadHive.btnExecRegEditClick)
Use of Process Token Privileges in Delphi (See below)

RE: Hives
The WinXP registry is divided into many different sections. Each major section is called a hive. Handling complete branches of the registry as separate hives allows Microsoft to perform several neat tricks. First of all, it allows hive to appear in several places in the registry with different names. The most obvious example of this is HKey_Current_User which of course points to the hive of the user that has logged in. A lesser known example is HKEY_CLASSES_ROOT which is simply a reloaded version of KEY_LOCAL_MACHINE\SOFTWARE\Classes. Those familiar with the DOS subst command and Linux symbolic links can draw comparisons there too.

An even lesser known use of windows hives is that Windows does not keep all of its hives active. It has separate hives to use as examples for creating local users, and other for creating user accounts when someone has logged into the machine remotely through a domain. I seem to remember there being a couple more examples but they elude me at the moment. Those hives are stored as DAT files on the hard drive. For instance, in the default XP install, the registry hive stored at ‘c:\\Documents and Settings\\Default User\\NTUSER.DAT’ will be used to set all the default registry entries whenever a new user logs into the machine. Set a value in that hive, and all future users will have that value.

NOTE: Do not confuse this with HKEY_USERS\.DEFAULT. The HKEY_USERS\.DEFAULT hive stores the values used when no one is logged in. “Huh? How could that be useful?” Well, if you think about it, controlling whether or not a computer puts itself to sleep if some one has booted it but not logged in can be very important. It might also be nice to set a screensaver that works when you log out of your computer but leave it turned on. An ultra secure person could set the color scheme to be entirely black on black, then only a person that really knows what they are doing could log into the computer – LOL. In any case, .DEFAULT and the Default User hives are NOT the same thing.

RE: Token Privileges:
Windows XP/NT/2000 and newer operating systems have advanced security methods to restrict what programs can and cannot do. These restrictions also allow the logging of some restricted access functions. So, for example, while it is possible for programs to set the system time, just any old program can’t do it.

The program has to ask for and get permission to update the time, before it can be accomplished. It is a bit like what a bell hop must do to get into someone’s hotel room. If a bell hop needs to get into room 5321 (let’s pretend this hotel uses keys and not plastic cards), the bell hop will tell his manager he’s gonna need to get into a room, look up which key that room needs, ask the manager for that key, unlock the room and do his thing. Then of course he will lock the door as soon as he is done. Note that if the bell hop does a bunch of other things before locking the door, the room could be burglarized. And when a good bell hop has to access the room several times, the room will be locked between times he is accessing it.

The process for Windows is the same:
Tell Windows you will be adjusting privileges by calling: OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TTokenHd);
Find the local name of the privilege you will be adjusting by calling LookupPrivilegeValue
Grant yourself access by setting TTokenPvg.Privileges[0].Attributes to SE_PRIVILEGE_ENABLED
Lock the door again by setting TTokenPvg.Privileges[0].Attributes to SE_PRIVILEGE_DISABLED

In my program, I have created three helper routines for working with the tokens: SetTokenPrivilege, GrantPrivilege and RevokePrivilege. The latter two only serve to make my calling code clear. Readability is essential for any professional grade program. At some point you will forget the details of every single program you’ve write. So, even if you are only writing a routine for your own use, you should do what you can to make it easier to read. Tasks like this may seem wasted on throw away programs, but the more you do it, the faster you will be and the more likely it will be that your habit of writing good code will pay off in the end.

Here are my Delphi privilege routines:

[Delphi]
{******************************************************************************
SetTokenPrivilege
A helper function that enables or disables specific privileges on the
specified computer. A NIL in SystemName means the privilege will be granted
for the current computer. Any other value must match the name of a computer
on your network.
******************************************************************************}
procedure SetTokenPrivilege(aSystemName: PChar; aPrivilegeName: PChar; aEnabled: Boolean);
var
TTokenHd: THandle;
TTokenPvg: TTokenPrivileges;
cbtpPrevious: DWORD;
rTTokenPvg: TTokenPrivileges;
pcbtpPreviousRequired: DWORD;
TokenOpened, ValueFound: Boolean;
begin // SetPrivilege
// The privilege system is only available on NT and beyond
if (Win32Platform = VER_PLATFORM_WIN32_NT)
then begin
// Retrieve the Token that represents this current application session
TokenOpened := OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
TTokenHd);

// Check for failure
if (not TokenOpened)
then raise Exception.Create(‘The current user does not have the access required to run this program.’)
else begin
// Get the name of the privilege (since Windows is multi-lingual, this must be done)
ValueFound := LookupPrivilegeValue(aSystemName, aPrivilegeName, TTokenPvg.Privileges[0].Luid) ;
TTokenPvg.PrivilegeCount := 1;

// Enable or disable the flag according to the bool passed
if (aEnabled)
then TTokenPvg.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else TTokenPvg.Privileges[0].Attributes := SE_PRIVILEGE_DISABLED; // See note on local constant declaration
cbtpPrevious := SizeOf(rTTokenPvg) ;
pcbtpPreviousRequired := 0;
if (not ValueFound)
then raise Exception.Create(‘This program is incompatible with the operating system installed on this computer.’)
else begin
try
// Adjust the permissions as required.
Windows.AdjustTokenPrivileges(TTokenHd, False, TTokenPvg, cbtpPrevious,
rTTokenPvg, pcbtpPreviousRequired);
except
raise Exception.Create(‘The current user does not have the required access to load a registry hive.’)
end;
end;
end
end;
end; // SetPrivilege
{******************************************************************************
GrantPrivilege
This routine grants the privilege(s) needed to access the hidden system hive
and load it into memory.
******************************************************************************}
procedure TfrmLoadHive.GrantPrivilege(aPrivilegeName: String);
begin // GrantPrivilege
SetTokenPrivilege(NIL, PChar(aPrivilegeName), TRUE);
end; // GrantPrivilege

{******************************************************************************
RevokePrivilege
This routine revokes privilege(s) given in GrantPrivilege
******************************************************************************}
procedure TfrmLoadHive.RevokePrivilege(aPrivilegeName: String);
begin // RevokePrivilege
SetTokenPrivilege(NIL, PChar(aPrivilegeName), FALSE);
end; // RevokePrivilege
[/Delphi]

In my case, I am using the SeRestorePrivilege token. This is actually one of the most powerful and lethal tokens. With it you are telling Windows that you are a Hard Drive backup program and you want to have access to all sorts of files that most programs are not allowed access to. Presumably you are doing this for good and not evil. Other tokens are:
SeCreateTokenPrivilege, SeAssignPrimaryTokenPrivilege, SeLockMemoryPrivilege, SeIncreaseQuotaPrivilege, SeUnsolicitedInputPrivilege, SeMachineAccountPrivilege, SeTcbPrivilege, SeSecurityPrivilege, SeTakeOwnershipPrivilege, SeLoadDriverPrivilege, SeSystemProfilePrivilege, SeSystemtimePrivilege, SeProfileSingleProcessPrivilege, SeIncreaseBasePriorityPrivilege, SeCreatePagefilePrivilege, SeCreatePermanentPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeShutdownPrivilege, SeDebugPrivilege, SeAuditPrivilege, SeSystemEnvironmentPrivilege, SeChangeNotifyPrivilege, SeRemoteShutdownPrivilege, SeUndockPrivilege, SeSyncAgentPrivilege, SeEnableDelegationPrivilege, SeManageVolumePrivilege
So, that’s the basics. Take a look a the comments in the rest of the source code and you’ll soon see what happens and why.

Also try some different things. Run RegEdit and load the hive manually through File>Load Hive. Did you notice that you HAVE to be at a point within one of the preloaded hives before that option is enabled? What happens when you press the load hive button but you haven’t granted yourself privileges? What happens when you grant your self privileges and don’t revoke them b4 closing the program. Can you then load the hive when you rerun the program? What happens if you Grant 4 time but only unload once?

Experiment. But remember, you are playing with the registry and thar be monsters there. This app works fine on my system, I’ve used similar routine regularly for a couple years now, but I haven’t tested it with all versions of Windows and I have no idea how it will handle out-of-the-ordinary circumstances, like bad sectors in a dat file on your HD. Additionally, a Windows Service pack could totally change what this program does. So, in short, don’t come to me when you need to reinstall Windows. I’ll simply say it was a bad coincidence and anyway your system is beyond my control, you never should have run this program on it. I’m not responsible for your financial and emotional loss. You are responsible for making sure that source code you run on your computer does not have deliberate or accidental malicious behaviors.

http://www.TheCodeCave.com/downloads/delphi/LoadHiveDemo.exe
http://www.TheCodeCave.com/downloads/delphi/LoadHiveDemo.dpr
http://www.TheCodeCave.com/downloads/delphi/U_LoadHive.dfm
http://www.TheCodeCave.com/downloads/delphi/U_LoadHive.pas

A batch file to find the first matching file in the search path…

This is another small app I wrote for someone to use at the ZTree forum.

This one is a DOS batch file that finds files in your search path that match the criteria you pass to it.
For instance you could type “SearchPath WPFile.Doc” and it would return the location of that file in your search path. If you type in simply “SearchPath MyApp” it will do a search for all executible files as defined by the PATHEXT environmental variable.

I found this program extremely useful since when clicking Start>Run and entering NO (it was supposed to autocomplete to notepad) ran a program that I could not find anywhere. SearchPath found it in a network directory.

Concepts Demonstrated:
Batch file subroutines – Use a CALL to execute a jump location in the same batch file as if it was a seperate batch
GOTO :EOF – Used to return out of a batch file OR batch Subroutine.
For Loops & Accessing to Environment variables
Child Recursion – A parent calls the child and the child in turn calls the parent which could in turn
child again.

[DOS]
:: *************************************************************************
:: SearchPath.Bat 10/31/2005
:: Written by Brian Layman (AKA Capt. Queeg)
:: Visit him at http://www.TheCodeCave.com
::
:: A batch written to display the program that would be run when
:: a filename is typed at the command prompt. Just a demo for
:: Hartmut at http://www.ztw3.com/forum/forum.cgi
::
:: Usage: SearchPath ProgramName[.EXT]
::
:: History:
:: 10/31/2005 – BL – Created
:: 11/01/2005 – BL – Removed Temp File Usage
::
:: *************************************************************************
@echo Off
:: All this is boiled down to one subroutine that sets a variable of the
:: same name.
call :SearchedFilePath %1

:: If no program is found, say so.
if “%SearchedFilePath%”==”” echo There is no matching program in the search path

:: If a program was found, echo its name.
if NOT “%SearchedFilePath%”==”” echo %SearchedFilePath%

:: Clear out our temp variable
set SearchedFilePath=

:: Quit
GOTO :EOF
:: *************************************************************************

:: *************************************************************************
:: Support procedures
::
:: These routines are called with a CALL directive and the GOTO :EOF
:: terminates that CALL but does not terminate the entire running of the
:: batch file.
:: *************************************************************************

:: *************************************************************************
:SearchedFilePath
:: Returns the full path to a passed file in the searchpath
::
:: Returns blank if not found.
::
:: *************************************************************************
: set SearchedFilePath=
:: Set the default value to blank.
set SearchedFilePath=

:: If there is no extension handle it
if “%~x1″==”” Call :SearchWithExtensions %1&GOTO :EOF

:: There is no extension, is it blank?
if “%1″==”” GOTO :EOF

:: So, we have an extension. That means we can do a simple search.
:: %~dp$PATH:1 automatically searches the path for us. It is a
:: variable set by the Call command.
set SearchedFilePath=%~dp$PATH:1%1
if “%SearchedFilePath%”==”%1” set SearchedFilePath=&GOTO :EOF
GOTO :EOF
:: *************************************************************************

:: *************************************************************************
:SearchWithExtensions
:: Iterates the extensions gathered from the PATHEXT environment
:: and searches until the file is found.
::
:: Returns blank if not found.
::
:: *************************************************************************
:: Initialize a counter for looking at multiple search results in one line
set cnt=0

:SearchLoop
:: Break out after 20 checks.
:: If you might have more than 20 extensions, increase this value.
:: If you could find out how many periods there are in the temp file,
:: you could optimize this.
if “%cnt%”==”20” GOTO :SearchLoopCleanup
set /A cnt=%cnt%+1
:: Continually search the single line file returning each sequential
:: search result and recursively pass it to the SearchedFilePath routine.
:: When we ask for a token # that doesn’t exist and blank is returned,
:: abort out.
for /F “tokens=%cnt% delims=.;” %%C in (“%PATHEXT%”) do call :SearchedFilePath %1.%%C
if “%SearchedFilePath%”== “” GOTO :SearchLoop

:SearchLoopCleanup
:: Clear our Temp variable
set cnt=
GOTO :EOF
:: *************************************************************************[/DOS]

A small app to gather specific lines from files

Here’s a small app that I wrote to help out Pat Gilbert over on the ZTree support forums.

And I quote: http://www.ztw3.com/archive/020/archive.cgi?read=72807

> What I need to do is to “gather” the 3rd & 4th lines of text
> from a set of files and write them to a temporary file for further
> processing. Ideally I would like them appended to the temp file without
> additional LFCR at the end of each gather.

I sometimes give myself a 15 minute project to write on Monday mornings to clear my brain and get my mind into the right mode. I REALLY needed that this morning, so I threw this together. With testing, I exeeded my 15 minute time limit by 5 minutes, so you’ll need to figure out how to use it yourself, but here:
http://the-wildwest.com/Queeg/Batches/GatherLines.exe

Click the ChangeDirectory button to populate that edit box with the currend path.

Save to file will save a file called Gathered.txt to the current directory (which is probably where you are gathering lines from.).

It could be MUCH more efficient and if you are working with Largish files, it will be slow (for convenience I load the whole file), but like I said, I had 15 minutes.

Maybe it will help…

Free Microsoft Visual Studio 2005 Standard Edition

or “How to get into the game development business cheaply” pt. 1.”

Microsoft does these promotions periodically. Microsoft isn’t REALLY into the individual developer compiler business anymore – that’s not where the cash is. They want to sell multiple enterprise copies to businesses and the more developers at those big companies that are already familiar with their products, the more easily the company will make a capital investment. Standard editions have become MS’s marketing & educational tools. So, they just give away them away after a little indoctrinization.

This site one way to get your own copy: www.learn2asp.net. Just listen to three presentations and they’ll mail you a copy of MS VS 2005 SE. You can sign in using a hot mail account and give them a “separate” mailing address.

Microsoft® Visual Studio® 2005 Standard Edition Includes:

  • Microsoft Visual Basic®,
  • Microsoft Visual C#®,
  • Visual C++®,
  • Microsoft Visual J#®
  • Tools for building Windows® and Web solutions
  • SmartPhone and Pocket PC development tools
  • Tools for visually designing databases, queries, and stored procedures

This is what the demos look like:
http://www.thecodecave.com/PHPvsASP.wmv

Safe Source Code Highlighting in WordPress 2.02 – Take 2

Well the good news is that the Syntax highlighting is back!

I’ve found another implementation of the GeSHi Syntax highlighter. This one is under current development and in fact version 3.5 (as opposed to 0.2 of that OTHER highlighter) was just released a week or two ago.

The igHiliter 3.5 is available here: http://blog.igeek.info/still-fresh/2006/02/25/code-for-fun/
Now, instead of using braces and code tags, I must use brackets:
[html]

10 Goto 10

[/html]

I use brackets like so:
[code]
[somelang]
10 Goto 10
[/somelang]
[/code]

This seems to work VERY well, but having learned my lesson, I’ll hold my review till I’ve had a chance to fully test. I’ve already made some changes to the source code to, IMHO, improve the appearance and make it look a bit more standard & professional. I was pleasantly surprised by the quality of the source code. The simple fact that it is consistent in its Styles and Standards (capitalization & spacing), well commented and easy to read, carries high marks in my book.

The integration with GeSHi has been done very smoothly. The standard languages supported in the program are quite sufficient for my needs (a bit over kill really since I won’t be touching Ruby any time soon and while I’ve used it, I won’t be posting Python here any time soon either. So, the author wisely choose not to provide built in support for all possible GeSHi languages. Instead, the plugin is fully compatible with all GeSHi plugins. You gotta love a plugin with plugins. Where will it end?!?!?!

And I learned something new tonight too.

All of those buttons above the editor are contained within the file:
/wp-includes/js/quicktags.js

The format is pretty straight forward. So, for instance, to add a button for the delphi tag, I just put in:
[javascript]
edButtons[edButtons.length] =
new edButton(‘ed_shDELPHI’
,’DELPHI’
,'{delphi}’
,'{/delphi}’
,”
);
[/javascript]

Actually, I’d use brackets instead of braces, but you get the idea.
Those fields are
1. Button Label
2. Openning tag
3. Closing tag
4. Hot key
5. Open Ended Key (0/blank=FALSE -1=TRUE=tag does not need to be closed)

I’ve got some plans for this file!!!!

GeshiSyntaxColorer WordPress Plug in – DON’T USE IT in WP 2.02

WAS: Safe Source Code Highlighting in WordPress 2.02

Since this is a blog large to be devoted to source code segments, I REALLY wanted to be able to do the kind of code highlighting I’ve seen in Forum software such as that used at Codingforums.com. An inadvertent search for how to do a StrToInt (that’s a Delphi function) in PHP (the answer is IntVal()) I found a php unit with Delphi references. I thought it was a neat little unit so I bookmarked it. It turns out it was part of the source code for GeSHi the Generic Syntax Highlighter. Geshi was the syntax highlighter built into phpBB. It since grown into a fully independent universal PHP class available over at http://qbnz.com/highlighter/index.php

The latest stable version of GeSHi is 1.0.7.7, released on the 25th of February, 2006.

Supported Languages: Actionscript; ADA; Apache Log; AppleScript; ASM; ASP; AutoIT; Bash; BlitzBasic; C; C for Macs; C#; C++; CAD DCL; CadLisp; ColdFusion; CSS; Delphi; DIV; DOS; Eiffel; FreeBasic; GML; HTML; Inno; Java; Java 5; Javascript; Lisp; Lua; Microprocessor ASM; MySQL; NSIS; Objective C; OCaml; OpenOffice BASIC; Oracle 8 SQL; Pascal; Perl; PHP; Python; Q(uick)BASIC; robots.txt; Ruby; Scheme; SDLBasic; Smarty; SQL; T-SQL; VB.NET; Visual BASIC; Visual Fox Pro; and XML.

I was absolutely tickled when on a whim I did a search for Geshi and WordPress to see if anyone else had tried to integrate it and low and behold, I suddenly found a GeSHi plugin over at the worpress plugin site.
http://dev.wp-plugins.org/wiki/GeshiSyntaxColorer.

It works beautifully. Especially since it stays within the width of hte columns and no other highlighting boxes I tried had done that without specific widths begin set.

You can already see it at work in php and delphi code form earlier posts here. Enjoy!

[edit] Grrrrr… Something I’ve done has changed my blog so that I must explictly specify <br /> at my end points!!! [/edit]

[edit] Double Grrrrr… It is the GeSHI plug in! it is stripping out all p tags from the whole page!?!?!?!?!

Gack…. the plug in is fatally flawed…. This is disappointing… I liked all of my color code…
[/edit]

[edit]
OK – Here’s the fix – use the igHiliter. It seems to work MUCH better. More on this later.
[/edit]

The problem with multiple checkboxes

(Have I mentioned that I HATE the TinyMCE implementation in WordPress… I appologize if you came to this post after I edited it changing one letter which allowed TinyMCE to totally scramble it!)

While creating the entry form for the WordPress 2.0 Theme database, I had to learn a bunch of stuff.

First I’d only every created two forms before and one of them only had one field, but I was very proud of it. 🙂

See:
http://forums.the-wildwest.com/checkip.php

It uses the first of several form submission techniques: GET

You can tell a GET form because when you hit submit, you go to a page with a new url followed by a question mark and a bunch of values seperated by ampersands. Since it is a GET, and I didn’t know enough then, it was vulnerable to some of the methods used to attack servers. For instance, I could inject HTML into the url and have it processed in the form like this:
http://forums.the-wildwest.com/checkip.php?ip=I%20should%20not%20be%20able%20to%20put%20HTML%20here

The result was that when I displayed the value for $ip, the HTML code that I put in that value would have been executed. In my simple example the text would have been displayed in bold. NO WHERE in the form should the text I put in there be bold. But it was. I SHOULD have strip all html tags out of my values before displaying them, but I didn’t know any better then. AND bigger and better people than me have made that same mistake. In fact, many of the problems in the WordPress release were at least somewhat related to this technique.

The fix was simple I took the code:
[PHP]
if (!(isset($ip))){
$ip = $_SERVER[‘REMOTE_ADDR’];
}
[/PHP]

and changed it to

[php]
if (!(isset($ip))){
$ip = $_SERVER[‘REMOTE_ADDR’];
}
else {
$ip = htmlspecialchars($ip);
}[/php]

That way, if the variable was blank, I filled it in. If the variable included html, I cleaned it up so that it would not execute. Well, that’s enough of a hacking lesson for now. I will post more ways to protecting your in a different post later. Back to creating forms…

As always W3 Schools has some of the best information about forms and you can see how the GET method can be used to retrieve information from the user in a bunch of different ways. http://www.w3schools.com/html/html_forms.asp

In my Theme submission form, I ask for about 20 different fields to be (optionally) filled in including a description field that could be up to 200 characters long. EVERY submission would likely produce an url that was too long for the Browser to handle. So, using the GET method was right out. I was on new ground.

The method of submitting information I would have to use is the POST method. It sends the information to the server in the array variable $HTTP_POST_VARS. Then you must use PHP or PERL or CGI or whatever to process it. (BTW any method is subject to the HTML injection, so I must parse it too. It is just more when obvious using GET.)

However as it turned out, the POST method seemed to work differently than GET when filling out multiple check boxes and that was something I REALLY wanted to do. My end goal was to take mutiple check boxes and turn them into a binary bitmapped field. That’s an integer value that when looked at in binary represents all of the checked boxes. So the value of 1010101 means that every other check box is checked. And that would be stored in a database integer field as the integer 85.

See, I’m lazy. I could easily make a form with 20 different checkboxes each having a seperate field in the database. But if I’m going to go to the effort of creating a table that stores descriptions of things submitted to my website, I’m going to make it generic and reuse it for all sorts of things. So not only will this be a table for storing theme information, but it will also store the information for the pictures of knitting projects from my wife’s book for here www.knitchat.com website. It will also store pictures of Kits sent down to Missisipi for the Katrina relief project at www.PurlsOfHope.com. Who knows what else I’ll use it for…

Anyway, to create multi-selectible checkboxes, you just put a bunch of checkboxes with the same name (again go to w3schools for the basics of fields).

My sample code worked as desired if I used a Get method to display the result of multiple check boxes.
See here: http://www.Thecodecave.com/MultipleXBox_Get.php
See all of those values in the address bar? There are a bunch of them for the flag check boxes. that’s what I wanted.

However, if I use a Post method do submit the form, I only get one value back, the last one, from my multiple check boxes. See: http://www.Thecodecave.com/MultipleXBox.php

I could find no documentation supporting that said multiple check boxes worked differently under the POST method, but they do!!!

Here’s my original code:
[php]
“;
echo “$ Submit = “.$submit.”
“;
if ($submit) {
echo “Here is what was submitted:
“;
if(is_array($HTTP_POST_VARS)) {
reset($HTTP_POST_VARS);
while (list($key, $val) = each($HTTP_POST_VARS)) {
if (is_array($val)) {
while (list($akey,$aval) = each($val)) {
$HTTP_POST_VARS[$key][$akey] = strip_tags($aval);
echo “Array Value: “.$key . “=” . htmlspecialchars($HTTP_POST_VARS[$key][$akey]).”
“;
}
}
else {
$HTTP_POST_VARS[$key] = strip_tags($val);
echo “Val: ” .$key . “=” . htmlspecialchars($HTTP_POST_VARS[$key]).”
“;
}
}
}
}
else {
?>

Submission

f1
  • f2

  • f3

  • f4

  • f5

  • f6

  • f7

  • f8

  • f9

  • f10




  • [/php]

    In the end, thanks to the peope over at CodingForums.com, I was able to get it to work. I was missing a simple peice of information. To get Multiple field values to work using a post method, you MUST have them populate an array. How do you do that? Simple: put empty brackets after the field name.

    So, I just changed my code like this:
    [php]


    • f1

    • f2

    • f3

    • f4

    • f5

    • f6

    • f7

    • f8

    • f9

    • f10


    [/php]

    and it works great!

    You can see it in action here: http://www.Thecodecave.com/MultpleXBox_Fix.php

    (Have I mentioned that I HATE the TinyMCE implementation in WordPress… I appologize if you came to this post after I edited it changing one letter which allowed TinyMCE to totally scramble it!)

    While creating the entry form for the WordPress 2.0 Theme database, I had to learn a bunch of stuff.

    First I’d only every created two forms before and one of them only had one field, but I was very proud of it. 🙂

    See:
    http://forums.the-wildwest.com/checkip.php

    It uses the first of several form submission techniques: GET

    You can tell a GET form because when you hit submit, you go to a page with a new url followed by a question mark and a bunch of values seperated by ampersands. Since it is a GET, and I didn’t know enough then, it was vulnerable to some of the methods used to attack servers. For instance, I could inject HTML into the url and have it processed in the form like this:
    http://forums.the-wildwest.com/checkip.php?ip=I%20should%20not%20be%20able%20to%20put%20HTML%20here

    The result was that when I displayed the value for $ip, the HTML code that I put in that value would have been executed. In my simple example the text would have been displayed in bold. NO WHERE in the form should the text I put in there be bold. But it was. I SHOULD have strip all html tags out of my values before displaying them, but I didn’t know any better then. AND bigger and better people than me have made that same mistake. In fact, many of the problems in the WordPress release were at least somewhat related to this technique.

    The fix was simple I took the code:
    [PHP]
    if (!(isset($ip))){
    $ip = $_SERVER[‘REMOTE_ADDR’];
    }
    [/PHP]

    and changed it to

    [php]
    if (!(isset($ip))){
    $ip = $_SERVER[‘REMOTE_ADDR’];
    }
    else {
    $ip = htmlspecialchars($ip);
    }[/php]

    That way, if the variable was blank, I filled it in. If the variable included html, I cleaned it up so that it would not execute. Well, that’s enough of a hacking lesson for now. I will post more ways to protecting your in a different post later. Back to creating forms…

    As always W3 Schools has some of the best information about forms and you can see how the GET method can be used to retrieve information from the user in a bunch of different ways. http://www.w3schools.com/html/html_forms.asp

    In my Theme submission form, I ask for about 20 different fields to be (optionally) filled in including a description field that could be up to 200 characters long. EVERY submission would likely produce an url that was too long for the Browser to handle. So, using the GET method was right out. I was on new ground.

    The method of submitting information I would have to use is the POST method. It sends the information to the server in the array variable $HTTP_POST_VARS. Then you must use PHP or PERL or CGI or whatever to process it. (BTW any method is subject to the HTML injection, so I must parse it too. It is just more when obvious using GET.)

    However as it turned out, the POST method seemed to work differently than GET when filling out multiple check boxes and that was something I REALLY wanted to do. My end goal was to take mutiple check boxes and turn them into a binary bitmapped field. That’s an integer value that when looked at in binary represents all of the checked boxes. So the value of 1010101 means that every other check box is checked. And that would be stored in a database integer field as the integer 85.

    See, I’m lazy. I could easily make a form with 20 different checkboxes each having a seperate field in the database. But if I’m going to go to the effort of creating a table that stores descriptions of things submitted to my website, I’m going to make it generic and reuse it for all sorts of things. So not only will this be a table for storing theme information, but it will also store the information for the pictures of knitting projects from my wife’s book for here www.knitchat.com website. It will also store pictures of Kits sent down to Missisipi for the Katrina relief project at www.PurlsOfHope.com. Who knows what else I’ll use it for…

    Anyway, to create multi-selectible checkboxes, you just put a bunch of checkboxes with the same name (again go to w3schools for the basics of fields).

    My sample code worked as desired if I used a Get method to display the result of multiple check boxes.
    See here: http://www.Thecodecave.com/MultipleXBox_Get.php
    See all of those values in the address bar? There are a bunch of them for the flag check boxes. that’s what I wanted.

    However, if I use a Post method do submit the form, I only get one value back, the last one, from my multiple check boxes. See: http://www.Thecodecave.com/MultipleXBox.php

    I could find no documentation supporting that said multiple check boxes worked differently under the POST method, but they do!!!

    Here’s my original code:
    [php]
    “;
    echo “$ Submit = “.$submit.”
    “;
    if ($submit) {
    echo “Here is what was submitted:
    “;
    if(is_array($HTTP_POST_VARS)) {
    reset($HTTP_POST_VARS);
    while (list($key, $val) = each($HTTP_POST_VARS)) {
    if (is_array($val)) {
    while (list($akey,$aval) = each($val)) {
    $HTTP_POST_VARS[$key][$akey] = strip_tags($aval);
    echo “Array Value: “.$key . “=” . htmlspecialchars($HTTP_POST_VARS[$key][$akey]).”
    “;
    }
    }
    else {
    $HTTP_POST_VARS[$key] = strip_tags($val);
    echo “Val: ” .$key . “=” . htmlspecialchars($HTTP_POST_VARS[$key]).”
    “;
    }
    }
    }
    }
    else {
    ?>

    Submission

    f1
  • f2

  • f3

  • f4

  • f5

  • f6

  • f7

  • f8

  • f9

  • f10




  • [/php]

    In the end, thanks to the peope over at CodingForums.com, I was able to get it to work. I was missing a simple peice of information. To get Multiple field values to work using a post method, you MUST have them populate an array. How do you do that? Simple: put empty brackets after the field name.

    So, I just changed my code like this:
    [php]


    • f1

    • f2

    • f3

    • f4

    • f5

    • f6

    • f7

    • f8

    • f9

    • f10


    [/php]

    and it works great!

    You can see it in action here: http://www.Thecodecave.com/MultpleXBox_Fix.php

    WordPress News for the week of 3/6/2006

    or “WordPress news finally posted a week late”

    With the “hacking” of the original WordPress 2.0 theme competition and a new security release of WordPress 2.0, it has been an exciting week. First a quick word on the competition then a break down of the changes in 2.01.

    Now about the competition: When WordPress 2.0 was released, everyone was looking for themes. And google led everyone to just a few places. The main one ended up being a competition site by someone known only as Justin. It seems now, even to an eternal optimist like myself, that it is likely that either the whole KyCap.com competion was a fraud or the Justin just got in over his head. Here are the final posts from that site:

    Better News

    6th March 2006

    I had contacted the server admin and they told me they will look into it and get back to be as soon as possible. At the mean time, i had received a lot of help e-mails from everyone on how to retrive back almost every post from the google cache. I am very grateful on this help. I would like to say thanks to those who help me out.

    Trying to retrive Database

    5th March 2006

    I am truely very sad on what happening to my competition blog. I took more than a month time planing everything up before i organise this competition to let everyone share their works. I don’t earn anything from this competition and i don’t even put up any google adsense to earn any side income. I just hope everyone could enjoy looking for a nice themes.

    Message to the hacker, “If you did clear up all this competition blog database, we got nothing to say but if you did save a backup for this database. Please send a copy to us to our email at kcyap@kcyap.com. We will appreciate if you could send it over as soon as possible”

    It is really everyone’s hard work on organising this competition. We spend most of our time trying our best to host the best competition ever.

    I am very happy with all the comments and the e-mails that had been sent to me regarding this incident. A lot of people had been helping me up on how to get back all the lost post. For your information, my whole database had been deleted by the hacker. Not even a thing left on my server directory. Luckily i did back at least something up for my personal blog. I guess the only way to retrieve all the lost post is trought google cache. Google cache doesn’t shows every page for my post that had been publish. Are there any better ways to retrieve them all?

    The themes will all be publish as we had moved them to a new server. The new server is sponsored by one of the followers for this competition blog. I will blog about it soon. Thanks.

    Website Got Hacked

    5th March 2006

    Very regret to announced that this competition blog website had been hacked. I have no backup for all this data and not sure if the server admin did have a backup on it or not. I am very sorry for this incident.
    The prizes will still be the same and i will upload once again all the submitted themes on by one from now. This may takes quite some time, please be patient.

    The result for this competition will still be announce don the 10th March 2006.

    To the sponsors who had agreed to sponsor for this prize, i wont put all the blame on your if u retrieve from sponsoring the prizes because of this incident. We will sponsor the prizes ourself. Luckily we did prepare on it.

    Anyone have any idea on how to get back all the deleted post ? Once again, i am very sorry on what had happened. I will try to get back the deleted post if possible. I guess today will be the worst day of my life after i’ve hardly organising this competition for over a month period.

    Ironically, it seems his website now HAS been hacked since it is totally crashed. It only displays "No such file or directory in /home/u1/ahkiongkc1/html/index.php" , something I am putting on record here since I can’t see any reationship between the name “Justin” and “achkiongks1”. But that is just matter for further speculation. On the positive side, there were several decent themes put up including the one I am using right now, Binary Blue by Count Zero.

    I’ve decided that I will actually put together a 2.0 theme database that people could log their themes to and even upload them for distribution if they don’t have the storage space. So, you’ll soon see some posts explaining what I’ve learned about web forms and fields. I think I’ve got all of the peices working now. 1. An Entry form with the fields I’d use to evaluate whether or not to download a theme. 2. A Page to allow the uploading of an archived theme to my site. 3. A page that performs the actual upload and validation and hopefully provides some protection from abuse security. Oh, and I need the form that iterates the database and displays the result in a table, but that’s easy. So I just need to put them together.

    NOTE: This will NOT be a theme competion. This is just a compendium or listing of themes. HOPEFULLY it will be the BEST listing of themes but it is in no way is this meant to compete with the new theme competion at http://www.wordpressarena.com/ which will stop accepting new themes in a week.

    Regarding Count Zero, and that’s the English translation – in German he would be known as Count Null (making his website www.4null4.de 404 like the invalid page error Get it? Get it?), we’ve been emailing back and forth all week and, despite my earlier comment about his Customer Relations skills (which I’ll have to rescind – I guess everyone is entitled to get grumpy now and again), I really like the guy. In spite of an off the wall conspiracy theory that he might actually be Justin (lol), I think a good friendship can evolve here, assuming I ever get around to reviewing his theme like I said I would last weekend.

    One of the things we’ve discussed over the last week is the security holes in the WordPress Blogging system. They did indeed exist. Count pointed me at where the flaw was and later that night I tested an attack on this website. Luckily the site I host this blog through has a setting that protects against that kind of attack I was using. I still want to determine which knitting blogs may be vulnerable to this kind of attack and tell them how to fix it. Yes I said knitting. With my wife’s knitting blog getting me into this, I feel like I should try to help that community with the technical sides of things. I already know there are a bunch of vulnerable sites. How to approach them is the key. I’m pretty sure that leaving a comment that changes the title of the post I am commenting on by adding a period to it is the wrong aproach. But it is still tempting and would get the point across. 😉

    The good news is that the the security in Worpress 2.02 fixes this particular vulnerability. The other good news is that no one has gone around taking advantage of this hole yet in the fashion that they could. KnitChat.com was actualy hacked twice through holes in WordPress 1.52 that have since been plugged. That allowed the index.php file to be replaced with a hacked version. As of tonight, I’m pretty sure I know how that was done. Repairing the attack was easy. If you haven’t taken the right precautions in your blog, this attack could do anything from deleting all of your posts, to wiping the whole DB or worse (yes there is worse).

    So, onto what has changed in 2.02 (this was supposed to be the meat of this post and was the only reason why I started it.) Since this is a security release, the WordPress developers didn’t do a detailed “Here is how you can attack older blogs” listing, but they could have gone further than they actually have. The people that will attack blogs, will already know how to compare files between versions and can write their own attacks. I want to know what holes there are in older systems so that I don’t make the same mistakes in what I write.

    BTW there will be a couple areas in which I am technically correct in what I say, but I am somewhat vague or don’t explain all of the effects of the code. These are intentional, please do not supply extra detail. However, if I am blatently wrong on something, let me know. Thanks!

    So here is the break down:

    End User Changes

    \WP-Comments-Post.PHP

    Old code:
    [php]
    51 $comment_id = wp_new_comment( $commentdata );
    52
    53 if ( !$user_ID ) :
    54 $comment = get_comment($comment_id);
    55 setcookie(‘comment_author_’ . COOKIEHASH, $comment->comment_author, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    56 setcookie(‘comment_author_email_’ . COOKIEHASH, $comment->comment_author_email, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    57 setcookie(‘comment_author_url_’ . COOKIEHASH, clean_url($comment->comment_author_url), time() + 30000000, COOKIEPATH, [/php][php]COOKIE_DOMAIN);
    58 endif;

    New code:
    [php]
    51 $comment_id = wp_new_comment( $commentdata );
    52
    53 if ( !$user_ID ) :

    54 setcookie(‘comment_author_’ . COOKIEHASH, stripslashes($comment_author), time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    55 setcookie(‘comment_author_email_’ . COOKIEHASH, stripslashes($comment_author_email), time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    56 setcookie(‘comment_author_url_’ . COOKIEHASH, stripslashes($comment_author_url), time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    57 endif;
    [/php]
    Why:
    See how the stripslashes was added? That is to ensure that the cookies that are stored on the poster’s computer contain the raw unprotected code. WordPress will do the protection each time a post is madeIf you protect an already protected entry, the data just gets garbled.

    [/php]See how the stripslashes was added? That is to ensure that the cookies that are stored on the poster’s computer contain the raw unprotected code. WordPress will do the protection each time a post is madeIf you protect an already protected entry, the data just gets garbled.

    \wp-register.PHP

    Old Code:
    [php]
    26 } else if (!is_email($user_email)) {
    27 $errors[‘user_email’] = __(‘ERROR: The email address isn’t correct.’);

    28 }
    29


    30 if ( ! validate_username($user_login) )
    31 $errors[‘user_login’] = __(‘ERROR: This username is invalid. Please enter a valid username.’);
    [/php]

    New code:
    [php]
    26 } else if (!is_email($user_email)) {
    27 $errors[‘user_email’] = __(‘ERROR: The email address isn’t correct.’);
    28 $user_email = ”;
    29 }
    30
    31 if ( ! validate_username($user_login) ) {
    32 $errors[‘user_login’] = __(‘ERROR: This username is invalid. Please enter a valid username.’);
    33 $user_login = ”;
    34 }
    [/php]

    Why:
    This is fairly straight forward. If the UserName or User Email supplied while registering contains invalid info, possibly from an attack, don’t leave the info there to be built upon. Just clear it out and have the user try again.

    Old Code:
    [php]
    68 <div id=”login”>
    69 <h2><?php _e(‘Registration Complete’) ?></h2>
    70 <p><?php printf(__(‘Username: %s’), “<strong>$user_login</strong>”) ?><br />
    71 <?php printf(__(‘Password: %s’), ‘<strong>’ . __(’emailed to you’) . ‘</strong>’) ?> <br />
    72 <?php printf(__(‘E-mail: %s’), “<strong>$user_email</strong>”) ?></p>
    73 <p class=”submit”><a href=”wp-login.php” mce_href=”wp-login.php”><?php _e(‘Login’); ?> »</a></p>
    74 </div>
    […]
    113 “user_login” id=”user_login” size=”20″ maxlength=”20″ value=”” />[/php][php]114 =”user_email” id=”user_email” size=”25″ maxlength=”100″ value=”” />

    [/php]New code:
    [php]
    71 <div id=”login”>
    72 <h2><?php _e(‘Registration Complete’) ?></h2>
    73 <p><?php printf(__(‘Username: %s’), “<strong>” . wp_specialchars($user_login) . “</strong>”) ?><br />
    74 <?php printf(__(‘Password: %s’), ‘<strong>’ . __(’emailed to you’) . ‘</strong>’) ?> <br />
    75 <?php printf(__(‘E-mail: %s’), “<strong>” . wp_specialchars($user_email) . “</strong>”) ?></p>
    76 <p class=”submit”><a href=”wp-login.php” mce_href=”wp-login.php”><?php _e(‘Login’); ?> »</a></p>
    77 </div>
    […]
    116 […]=”user_login” id=”user_login” size=”20″ maxlength=”20″ value=”<?php echo wp_specialchars($user_login); ?>” /><br /></p>
    117 […]=”user_email” id=”user_email” size=”25″ maxlength=”100″ value=”<?php echo wp_specialchars($user_email); ?>” /></p>
    [/php]

    Why:
    This two changes are simple too. Using wp_specialchars, it takes any OEM characters (and what not) and makes sure they are displayed correctly in the user login name and email. This is crucial in todays international world.

    \wp-settings.php

    Old code:
    [php]
    188 // If already slashed, strip.
    189 if ( get_magic_quotes_gpc() ) {
    190 $_GET = stripslashes_deep($_GET );
    191 $_POST = stripslashes_deep($_POST );
    192 $_COOKIE = stripslashes_deep($_COOKIE);
    193 $_SERVER = stripslashes_deep($_SERVER);
    194 }
    [/php]
    New code:
    [php]
    188 // If already slashed, strip.
    189 if ( get_magic_quotes_gpc() ) {
    190 $_GET = stripslashes_deep($_GET );
    191 $_POST = stripslashes_deep($_POST );
    192 $_COOKIE = stripslashes_deep($_COOKIE);

    193 }
    [/php]
    Why?
    Magic_quotes_gpc() is a setting for the PHP server on your site. It automatically protects PHP database applications (like blogs) from common security breeches. It is the ONLY reason why there are not hundreds of WordPress blogs being crashed out there. magic_quotes_gpc protects the four ways of submitting information to the server: Gets, Posts (puts), Cookies, and Server settings (Server in this case includes information from your machine). WordPress simulates Magic quotes and doesn’t rely on the server settings. However, it doesn’t want to do the work twice and scramble the input. This change removes the line removes the slashes put in by Magic Quotes for the Server variable. To be quite honest, I’m not sure why yet… The Server variables must be special somehow in that we do want to double protect them. This doesn’t seem to make any sense to me. To be quite honest, I expected to see more protection around the server variables since they are a commonly abused area and are often used means of attacking websites. Maybe not removing the slashes – and thus allowing double slashes? – adds more protection? however to me it seems that slashed slashes would just produce scrambled results…. Maybe the developers wanted to show proof positive that these areas were protected? I’m missing something here…

    Admin User Changes

    OK this post is getting Way to long. So I am not going to go into the level of detail I did for the other area.
    \wp-admin\admin.php – Protects a reference to plugins page
    \wp-admin\admin-functions.php – There were several areas of protection added to this routine. It largely centers around using processed/retreived variables rather than variables that could be overridden by the users. It also blanks out or closes post settings that have no default values.
    \wp-admin\admin-header.php – Enforces the priveledges to edit categories.
    \wp-admin\edit-pages.php – Protects post edits by using a processed variable rather than one that could be supplied by the user.
    \wp-admin\List-manipulation.php – Blocks hack attacks from malformed links.
    \wp-admin\menu-header.php – Adds the ablity for plugins to give admin notices in the header.
    \wp-admin\post.php – Ensures that posts can only be made by admins that have logged in through the control panel.
    \wp-admin\user-edit.php – Ensures that the edit user event comes from the admin control pannel and not a hack attack.
    \wp-admin\blogger.php – Adds a missing html header

    Suffice it to say that these changes largely protect blog administrators that allow their Users to post.

    Shared Units

    \wp-includes\comment-functions.php Protect WP from malformed cookies
    \wp-includes\functions.php Minor bug fix in date processing
    \wp-includes\template-functions-general.php Adjustments to the date display methods
    \wp-includes\template-functions-links.php The routine for testing user permissions was rewritten. Calls to that routine had to be updated.
    \wp-includes\version.php – Upped the version number
    \wp-includes\js\* – TinyMCE was updated.

    the update to TinyMCE makes better but it is STILL horribly broken. I’ve still decided to turn it off for writing posts. Re-Editing posts is just IMPOSSIBLE with it on. It probably works if you ONLY use the limited buttons that are at the top of the post box, but if you use more than that, it just messes up.

    Conclusions

    This release does protect WordPress users from several forms of attack. Some of which I hadn’t thought of myself. I still don’t fully understand why the system does not strip out the slashes in the _server varibles before it re-applies them. Perhaps someone can address that in the comments, but that change does further increase the protection of an already vulnerable area and perhaps there was an avenue of attack in that area that I cannot see at this point. However, I do strongly recommend you apply this update. It makes you safer from attacks and spamming.

    PHP Bitwise operaters…

    Bitwise Operators

    Example		Name		Result
    $a & $b		And		Bits that are set in both $a and $b are set.
    $a | $b		Or		Bits that are set in either $a or $b are set.
    $a ^ $b		Xor		Bits that are set in $a or $b but not both are set.
    ~ $a		Not		Bits that are set in $a are not set, and vice versa.
    $a<<$b		Shift left	Shift the bits of $a $b steps to the left (each step means "multiply by two")
    $a>>$b		Shift right	Shift the bits of $a $b steps to the right (each step means "divide by two")
    $a & $b		And		Bits that are set in both $a and $b are set.
    

    WordPress 2.0 themes are now available.

    The first of the WordPress 2.0 themes are up! I’m trying out the new BinaryBlue theme.  But it has a BIG surprise waiting for non-localized blogs that try it.  It will crash your blog and your admin pages.

    It is a localized theme. That means that you HAVE to have a special setting in your WP-Config .

    You know that section in wp-config.php that most of us have ignored? the one that says:
    [PHP]
    // Change this to localize WordPress.  A corresponding MO file for the
    // chosen language must be installed to wp-includes/languages.
    // For example, install de.mo to wp-includes/languages and set WPLANG to ‘de’
    // to enable German language support.
    define (‘WPLANG’, ”);

    [/PHP]
    Well, if you don’t have a value in there when you choose the new Binary blue theme, you only get this :

    Cannot instantiate non-existent class: cachedfilereader […]

    on every page of what you had previously thought of as your blog…

    Luckily, the fix is simple… change the define line in the config file to this:
    [PHP]

    define (‘WPLANG’, ‘en_US’);

    [/PHP]

    and your site will work again (after it does some initial chugging to apply the localization – give it half a  minute…)

    Beyond that, the theme is wonderfully well organized.  The options page is a treat and the developer, and you can see from his comments , that he is helpful and seems to know his stuff.  I’d like my WP3.0 theme to be as well organized.  This theme, though still 1.0, sets the standard that many should follow.

    I do wish there was a readme file that explained that step or that localization was turned off by default.

    I also tried turning on the ie7 “fixes” feature that the author gets tripple Kudos for turning into a configurable option rather than just building it in, and it caused some of my posts to wrap the sidebars down to the end of the page.  So that option is off again.

    I’ll try do a full review of it over the weekend.

    Hey, Kevin should create a blog entry for theme reviews that we can all point our tracebacks to…   Good idea?