Solar Bug Tracking
Bug tracking for Solar is now available at http://solarphp.com/bugs.php. This is the proof-of-concept Solar_App_Bugs application (eat your own dog food, right?).
Don't listen to the crowd, they say "jump."
Bug tracking for Solar is now available at http://solarphp.com/bugs.php. This is the proof-of-concept Solar_App_Bugs application (eat your own dog food, right?).
Solar is a simple object library and application repository for PHP; Solar applications bear some superficial resemblance to Ruby on Rails. Above all, Solar code is comprehensible and easy to understand, even for the relatively new PHP programmer, because it is exceptionally well-commented and adheres to a simple, straightforward style.
This is a bugfix release. You really should join the Solar mailing list; some good info on setting up Solar.config.php is there.
The changes notes for this release are:
* WARNING: This is a public development release, and is not
yet stable.
* Solar::start() now automatically shares and starts a Solar_User
object ('user') ... this makes sure authentication is always
processed.
* Solar_App::automap() now only attempts scandir() if the
requested directory actually exists.
* Solar_App_Bugs controllers for edit.php and item.php would
try to add the bug summary as the comment subject line,
but the max subject line is 64 chars (the max summary is
255) ... this would cause silent errors and fail to add
the comment. S_A_Bugs no longer adds a subject line,
which seems to correct the issue.
Well, I just signed up for PHP Tropics conference in Cancun being held by PHP Architect. This is my first PHP conference, and I'm really looking forward to meeting in person some of the people with whom I have corresponded for so long. And goodness knows I need a vacation. :-)
Solar is a simple object library and application repository for PHP5. This is a development release made in the middle of the night due to insomnia. ;-)
Among other things, there is a second proof-of-concept application included; Solar_App_Bookmarks mimics and extends a lot of del.icio.us functionality. I'm already using it instead of del.icio.us, as I can assign arbitrary ranks to links and then get an RSS feed in that order, instead of descending by timestamp.
Finally, I've started an open wiki for documentation (now that I have two good working apps I think it's time to describe how to install and use them ;-).
The change notes are:
* WARNING: This is a public development release, and is not yet stable. * WARNING: There are database schema changes in this release. * Fixed bug in Solar::pathinfo(); elements were all off by 1 (needed to shift off the first returned element, as it is always blank). * In Solar_Sql_Entity::buildSchema(), the 'join' value must now be a $schema['rel'] keyword. * Solar_Sql_Entity::update() now retains primary keys in a separate array (instead of unsetting them entirely) and restores them after the update process; this will help with post-update tasks that need the primary key. * Solar_Sql_Entity::selectCount() and selectPages() have been combined into countPages(), which returns an array with both the row count and the page count. * Solar_User_Auth_Htpasswd now rejects DES-encrypted passwords longer than 8 characters due to a limitation in crypt(). Have added support for SHA1 (thanks Tomas Cox) and APR1-MD5 (thanks Mike Wallner) encrypted passwords to offset this. * Added Solar_User_Auth_Multi to perform authentication against multiple fallback sources. * Solar_User_Role now uses a single role driver class by default. * Added Solar_User_Role_Multi to pull from multiple group/role sources. * Renamed Solar_Cell_Talk to Solar_Cell_Comments for clarity (this includes a set of schema changes as well as in-place support for trackback and pingback storage). * Schema changes to Solar_Cell_Bugs. * Added Solar_Uri as a URI import/manipulate/export tool, generally useful for building navigation links. Works with query elements as well as path_info elements. * Added Solar_Cell_Tags as a shared tag-search resource to support ubiquitous tagging across all Solar applications. * Added Solar_Cell_Bookmarks and Solar_App_Bookmarks for bookmark management similar to the del.icio.us service. * Various locale string additions and modifications.
(Well, sort of fixed.) This post originates from an issue I had with htpasswd files and crypt(); effectively, crypt() only looks at the first 8 characters in a password and validates if they match, regardless of the rest of the password. It turns out this is a known limitation of crypt(); it generated a fair amount of discussion on the pear-dev mailing list.
So while Solar_User_Auth_Htpasswd will still reject passwords longer than 8 characters as a security measure against the default DES crypt() limitation, I have been able to add support for SHA1 and APR1-MD5 encrypted passwords in htpasswd files. This will allow you to use much longer passwords. The new code comes courtesy of two PEAR developers: from a tip by Tomas V. V. Cox for SHA1, and from Mike Wallner's excellent crypt_apr_md5() method in File_Passwd. Thanks, guys!
(A side note: Apache htpasswd does not use a standard MD5 encryption routine, which is why just calling md5() from PHP was not a viable option.)
In working with Solar today, I discovered an issue related to the crypt() function and password files generated by Apache htpasswd. Technically, it's not a security issue with either of those fine programs, because they do work as documented and intended. However, due to my own ignorance of the limitations of crypt(), I created a security issue of my own; perhaps this post will help others avoid it.
The Solar_User_Auth class is very much like the PEAR Auth class, in that it lets you pick different container or storage types for your username/password authentication. You can use a database table, LDAP, POP or IMAP email account, a .ini file, and more. Similar to LiveUser, Solar_User_Auth also comes with a "Multi" container that lets you specify multiple authentication sources, so you can fall back from one to another automatically.
My problem today was with the "Htpasswd" container for Solar_User_Auth. Apache comes with a utility called "htpasswd" which lets you create a file of usernames and encrypted passwords. The file format is pretty straightforward; each line consists of "username:cryptedpass". To create a htpasswd file and insert the first username/password combination, you would issue "htpasswd -c /where/you/want/htpasswd.data -a someuser"; it will create the htpasswd.data file and prompt you for the password for "someuser", encrypting the password with the system crypt() function.
Now here's the thing about crypt() ... effectively, it only looks at the first 8 characters of the password to generate the encrypted hash. (Yes, there are ways to make crypt() use a longer salt, but that's not pertinent to this particular discussion, as we are only concerned with the way Apache htpasswd uses the crypt() function.)
Thus, if you have a password *longer* than 8 characters, as long as the first 8 characters match, crypt() will call it a valid match. For example, if your password is "password" and is stored as a crypted hash in a htpasswd file, checking against "passwordX" will be exactly the same as checking against "password", "password123", and so on; that is, it will be returned as a valid check because the first 8 characters match properly. Similarly, if your password is "longpassword" and you check against only "longpass", that will be returned as valid, too.
Obviously this is a problem. The solution, at least for Solar_User_Auth_Htpasswd, is that from now on, password checks longer than 8 characters will be rejected automatically as invalid. This sidesteps the problem entirely, even though it does limit users who want to use the Htpasswd driver to passwords of 8 characters or less. The next release of Solar will have this patch in place, and it has already been committed to the Subversion repository for Solar.
Have I missed anything important here? Has anyone else out there run into anything like this? If so, what was your solution?
Update: (2005-04-14) Although I'm retaining the 8-character limit under default DES encryption, I've added SHA1 and APR1-MD5 support, which should help a great deal.
Ryan King's Evolutionary Revolution has a lot of good info about making the web as we know it now a semantic datasource. He mentions, among other things, "microformats" (which are themselves a really useful tool that I'd seen but not understood).
Ryan's entry, along with the articles cited in his blogliography ;-), should give PHP developers good ideas on the kinds of things to support in their apps, possibly by making data from those apps automatically available in one of the various microformats. For example, there is the hCard format, a point-for-point XHTML representation of a text-based vCard. You can already parse vCards with Contact_Vcard_Parse, so rendering one from the generated array should be a relatively straightforward task. You could then take all your vCards, parse them from source text, and make a web-available resource from them.
Good post, Ryan; lots of food for thought.
This is a bugfix release; I failed to close parentheses properly in the block for extracting references (not the default behavior). You can get it from here (Savant3 is a PHP5 E_STRICT-compliant version of the Savant template system; see the website at http://phpsavant.com.)
This is part 4 in a 3-part series (take that, Douglas Adams ;-). You can see parts 1 and 2 here and part 3 here.
A little background: the reason I am so concerned portability is the Solar project. One of the stated goals for Solar_Sql (the RDBMS abstraction layer) is that it should run exactly the same way on every supported database. Right now, that list includes Frontbase, Microsoft SQL, MySQL, PostgreSQL, and SQLite.
Let's say we have a table with a column named "the_field" defined as CHAR(2). In the table, we have every possible combination of two letters, picked from the set of all upper-case and lower case letters (i.e., "A-Z" and "a-z", for a total of 26^2 rows in the table). For example, the "A" combinations are represented by four rows: "aa", "aA", "Aa", and "AA".
In theory, if you wanted to select the row with "aa" (where both are lower case), you would issue this SELECT statement:
SELECT * FROM the_table WHERE the_field = 'aa'
How many rows will you get back? You should only get one: the "aa" row. That's true if the database is PostgreSQL, Frontbase, or SQLite; however, in Microsoft SQL and MySQL, you get four ("aa", "aA", "Aa", and "AA"). That's because searches in those two RDBMSes are *not* case-sensitive on CHAR and VARCHAR fields. This fails to meet my requirement that Solar_Sql return the same results regardless of the backend.
I think the solution will be to re-define the native type used for "char" and "varchar" fields in those two databases. It turns out that in MySQL, a "CHAR(n) BINARY" and "VARCHAR(n) BINARY" both retain case-sensitivity in searches. In Microsoft SQL, the same appears to be true for "BINARY" (vice "CHAR") and "VARBINARY" (vice "VARCHAR").
Does anyone see a problem with using the binary types instead of the plain character types in those two databases, specifically for purposes of case-sensitivity? My appreciation will extend to buying you a beer next time we're in the same town. :-)