Andriy Gerasika's blog

Fixing "Page not found" in Drupal's OpenID

It is very often when you enable OpenID module in Drupal and try to login with OpenID, you receive "Page not found", whilst everything works quite fine at localhost.

The problem occurs after you have authenticated at OpenID provider website and it is redirecting you back to your website with URL in format: http://www.gerixsoft.com/openid/authenticate?destination=user&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.mode=id_res&...

The problem is that params of this redirect URL contain another URLs. Such kind of URLs are considered dangerous and are very often blocked by hosters by means of Apache mod_security module; it is mod_security that actually generates 403/404/Page not found.

One solution is to follow guidelines found on the net and ask your hosting provider to disable 1234234, 340151, 340153, 340163 mod_security rules. However after some time modifications may be reset and you will face the problem again. Another option is to disable mod_security but this is not secure and may expose your site to even bigger problems.

The solution I have come to is to selectively reverse the effect of mod_security in PHP code. The patch I have developed undoes 403/404 generated by mod_security for OpenID URLs only, rest of URLs are not touched. So both OpenID works and website is protected.

Just open index.php and put below code at line 20, just below "$return = menu_execute_active_handler();" code:

// © by Andriy Gerasika from GerixSoft, Ltd.
if (is_int($return) && $return == MENU_NOT_FOUND) {
	$uri = $_SERVER['REQUEST_URI'];
	$path = parse_url($uri, PHP_URL_PATH);
	if ($path == '/openid/authenticate' || ereg('^/user/[0-9]+/openid$', $path)!=false) {
		$path = substr($path, 1);
		$query = 'q=' . $path . '&' . parse_url($uri, PHP_URL_QUERY);
		$_SERVER['QUERY_STRING'] = $query;
		parse_str($query, $_REQUEST);
		parse_str($query, $_GET);
		$return = menu_execute_active_handler();
	}
}

P.S.
Now, once OpenID works in Drupal ok, you may give a try to my OpenID Selector Drupal module ;)

Nicer UI Font in Ubuntu

Next version of Ubuntu will include a new font, named "Ubuntu font", that will be used as default user interface font:

It is great Canonical have noticed default rendering of Bitstream Vera Sans in Ubuntu is not good, however this new font is not good either.

There is a much easier way to get nicer user interface font in Ubuntu without any new font(s).

Just go to System/Preferences/Appearance, and set Hinting to Slight and Resolution to 94 dots per inch.

Compare how above gedit window looks at my machine:

IMHO much much nicer compared to default DPI/smoothing settings in Ubuntu and much nicer compared to future "Ubuntu font".

I am using these settings for a number of years, since Dapper, and I guess by developing new font sometimes Canonical does not realize greatness of Ubuntu itself :)

P.S.
Mozilla Firefox and Thunderbird will emit somewhat larger fonts. To fix this for Firefox put attached userContent.css into ~/.mozilla/firefox/*/chrome folder; to fix this for Thunderbird put attached userChrome.css and userContent.css into ~/.mozilla-thunderbird/*/chrome folder.

Creating Threads in Delphi 2010

If you'll upgrade to Delphi 2010, you'll quickly notice that old code you were using to create threads, such as

constructor TMyThread.Create;
begin
  inherited Create({CreateSuspended}true);
 // must create event handle first!
  FEventHandle := CreateEvent(
          {security}      nil,
          {bManualReset}  true,
          {bInitialState} false,
          {name}          nil);
  Resume;
end;

now produces a warning:

[DCC Warning] xxx.pas(277): W1000 Symbol ‘Resume’ is deprecated

Of course, you can change Resume to Start and it will work, but that's not a proper way to create threads. The proper way would be:

constructor TMyThread.Create;
begin
 // create event handle first!
  FEventHandle := CreateEvent(
          {security}      nil,
          {bManualReset}  true,
          {bInitialState} false,
          {name}          nil);
  inherited Create({CreateSuspended}false);
end;

The trick is that Delphi does not require "inherited Create" to be the first statement in descendant constructor body.

Calling TObject.Create from descendant constructor does not create an object and does not write zeros to all of object fields. It is TObject.NewInstance method that does that.

The call "fMyThread := TMyThread.Create;" is actually compiled into two calls:

  1. The 1st compiled call is to TObject.NewInstance() method; this method allocates memory and initializes the fields
  2. The 2nd compiled call is to TMyThread.Create, invoked as any other regular method.

The same principle also applies to Destroy and FreeInstance methods: calling ancestor Destroy is not required to be the last statement of destructor's body.

JSON to XML in XSLT

XSLT is powerful enough to process even non-XML input. For example, I have created a transformation that converts JSON text to well structured XML output:

JSON text:

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber": [
         { "type": "home", "number": "212 555-1234" },
         { "type": "fax", "number": "646 555-4567" }
     ]
}

XML result:

 <?xml version="1.0" encoding="UTF-8"?>
<json>
   <object>
      <field name="firstName">
         <string>John</string>
      </field>
      <field name="lastName">
         <string>Smith</string>
      </field>
      <field name="age">
         <number>25</number>
      </field>
      <field name="address">
         <object>
            <field name="streetAddress">
               <string>21 2nd Street</string>
            </field>
            <field name="city">
               <string>New York</string>
            </field>
            <field name="state">
               <string>NY</string>
            </field>
            <field name="postalCode">
               <string>10021</string>
            </field>
         </object>
      </field>
      <field name="phoneNumber">
         <array>
            <object>
               <field name="type">
                  <string>home</string>
               </field>
               <field name="number">
                  <string>212 555-1234</string>
               </field>
            </object>
            <object>
               <field name="type">
                  <string>fax</string>
               </field>
               <field name="number">
                  <string>646 555-4567</string>
               </field>
            </object>
         </array>
      </field>
   </object>
</json>

It works by employing XML Pipeline technique:

  • first mode parses text using regular expressions and generates sequence of tokens in XML format: <comment>, <string>, <number>, <symbol>{</symbol>, etc.
  • second mode groups all tokens between "{" and "}" symbols into <object> element, between "[" and "]" symbols into <array> element
  • third mode makes a <field> element from <string><symbol>:<symbol>(<string>|<number>|<object>|<array>) sequence
  • fourth mode drops comma between consecutive <field> elements

and finally it performs XSD validation check.

This approach is quite exotic and non-standard, because when people hear word "parsing" they think of BNF, state-machine, AST, YACC, etc., but these technologies were created to parse complex programming languages.

I claim that XSLT coupled w/ regexp as tokenizer is powerful enough to convert simple markup languages such as JSON, CSS, MIF, RTF, wiki, etc., into XML.

p.s.
See attachment below for source code of the transformation.

OpenID Selector for Drupal

Drupal's OpenID module is somewhat not complete.

If you enable OpenID module in Drupal, it modifies user/login screen with "Log in using OpenID" link:

and when you click on that link, OpenID login form pop's up:

This form was always puzzling me: instead of remembering passwords, are now users supposed to remember their OpenID URLs?

For example, Google's OpenID URL format is "https://www.google.com/accounts/o8/id?id=<40-digit hash code>", and if user wants to login w/ Gmail account, is user supposed to type-in that string, or copy-paste the string from some place?

This form does not make Drupal's default login form any simpler, it makes it only harder. That's why I was never enabling OpenID module on any of my Drupal sites.

However, recently I was visiting SourceForge, and noticed they have incorporated OpenID login in a lot nicer form:

 

After viewing page source, I have figured out they are using openid-selector Javascript library from http://code.google.com/p/openid-selector/

Brief googling for "Drupal OpenID selector" did not produce any reasonable/good looking results except some weird commerical product at https://www.idselector.com/ (why make so simple thing so complex?)

Then I decided to write my own module integrating Javascript OpenID selector into Drupal.

After one day of heavy tweaking, I was able to marry it w/ Drupal's OpenID module.

Below is a screenshot of how OpenID login form now looks at http://www.gerixsoft.com/user/login

 

User profile's "OpenID identities" form at "/user/<id>/openid" has been enhanced w/ openid-selector as well.

Now, I release the module integrating OpenID Selector w/ Drupal as open source under GPL v2 license. You can find it attached.

Feel free to use it on your websites and unveil the true power of Drupal's OpenID module!

P.S.
The only drawback of the module is that it requires patching of Drupal core. After you've enabled it, you should open /modules/openid/openid.js, and comment out the following code (at line #23 as of Drupal version 6.17):

      $("#edit-openid-identifier")[0].focus();

You should restore(uncomment) this line back on disabling the module.

FOR XML in MSSQL

I am astonished of FOR XML feature in MSSQL. Oracle, despite claiming they had XML support first, has nothing like that; and XML support in PgSQL and MySQL is just ridiculuos...

The key feature of FOR XML is that is allows fetching multiple tables in just one query.

For example, below SELECT fetches Customer-Order-Shipper-OrderDetail-Product-Supplier-Category relationship:

SELECT *, (
    SELECT *, (
        SELECT *, (
            SELECT *, (
                SELECT Suppliers.SupplierID, Suppliers.CompanyName
                FROM Suppliers
                WHERE Suppliers.SupplierID = Products.SupplierID
                FOR XML PATH('Supplier'), TYPE
            ), (
                SELECT Categories.CategoryID, Categories.CategoryName,
                    Categories.Description
                FROM Categories
                WHERE Categories.CategoryID = Products.CategoryID
                FOR XML PATH('Category'), TYPE
            )
            FROM Products
            WHERE Products.ProductID = OrderDetails.ProductID
            FOR XML PATH('Product'), TYPE
        )
        FROM "Order Details" OrderDetails
        WHERE OrderDetails.OrderID = Orders.OrderID
        FOR XML PATH('OrderDetail'), TYPE
    ), (
        SELECT Shippers.ShipperID, Shippers.CompanyName
        FROM Shippers
        WHERE Shippers.ShipperID = Orders.ShipVia
        FOR XML PATH('Shipper'), TYPE
    )
    FROM Orders
    WHERE Orders.CustomerID = Customers.CustomerID
    FOR XML PATH('Order'), TYPE
)
FROM Customers
FOR XML PATH('Customer'), ROOT('xml'), TYPE

The question is not about receiving tables in XML, but about receiving all tables in just one call, w/ proper master-detail grouping (see attachment for result of the query). It is hard to imagine code doing the same w/ JOINs or cursors or on client-side. This makes FOR XML a perfect use-case in report generation services.

XSLT application servers would also greatly from FOR XML support: bespoke multiple tables can be fetched in one call, FOR XML produces results in XML format — just perfect for subsequent XSLT processing.

?mode in xsl:include/@href

The xsl:include/@mode patchset I have developed to ease XML Pipeline in XSLT is not good. The major problem is it won't work on closed-source XSLT processors (Saxon PE/EE for example).

As suggested by Michael Kay, there is a standard compliant way to implement above:

<xsl:include href="link1.xsl?mode=link1"/>

It would work by means of URIResolver performing XSLT preprocessing.

Using this approach chain.xsl would look like

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common">

    <xsl:output method="xml" omit-xml-declaration="no" indent="no" encoding="UTF-8"/>

    <xsl:include href="link1.xsl?mode=link1"/>
    <xsl:include href="link2.xsl?mode=link2"/>
    <xsl:include href="link3.xsl?mode=link3"/>

    <xsl:template match="/">
        <xsl:variable name="link1">
            <xsl:apply-templates mode="link1" select="node()"/>
        </xsl:variable>
        <xsl:variable name="link2">
            <xsl:apply-templates mode="link2" select="exsl:node-set($link1)/node()"/>
        </xsl:variable>
        <xsl:variable name="link3">
            <xsl:apply-templates mode="link3" select="exsl:node-set($link2)/node()"/>
        </xsl:variable>

        <xsl:copy-of select="exsl:node-set($link3)/node()"/>
    </xsl:template>

</xsl:stylesheet>

, link1.xsl, link2.xsl, link3.xsl and identity.xsl will be the same as in previous variant.

I have implemented ?mode in xsl:include/@href, and it works great.

The implementation works by using URIResolver and custom SAX ContentHandler. The ContentHandler is on-the-fly transforming XSLT source code adding mode attribute where necessary.

The reason I choose ContentHandler approach over simpler XSLT like

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

	<xsl:output method="xml" omit-xml-declaration="no" indent="no" encoding="UTF-8"/>

	<xsl:param name="mode"/>

	<xsl:template priority="-9" match="@*|node()">
		<xsl:copy>
			<xsl:apply-templates select="@*|node()"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="xsl:template[@match and not(@mode)] | xsl:apply-templates[not(@mode)]">
		<xsl:copy>
			<xsl:attribute name="mode">
		 		<xsl:value-of select="$mode"/>
			</xsl:attribute>
			<xsl:apply-templates select="@*|node()"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="xsl:include/@href | xsl:import/@href">
		<xsl:attribute name="{name()}">
			<xsl:choose>
				<xsl:when test="contains(., '?')">
					<xsl:value-of select="concat(., '&amp;mode=', $mode)"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat(., '?mode=', $mode)"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:attribute>
	</xsl:template>

</xsl:stylesheet>

is because ContentHandler approach preserves line number information: if you'll make an error in the source, processor will report exact line/col position of error; w/ above XSLT that is not possible.

You can find ZIP w/ source code implementing ?mode in xsl:include/@href attached below.

Syndicate content