• Friday, 23 May 2014

    Display Secure Atom Feeds in WordPress

    WordPress's built-in ability to broadcast and subscribe to RSS (short for "Rich Site Summary" or "Really Simple Syndication") and Atom feeds has led to a veritable "feeding" frenzy among WordPress users. This has in turn opened people's servers and devices to malevolent individuals. The possibility exists for a hacker to hijack a feed and infect it with malicious code, rendering your hosting server a target and propagator of the virus to your feed readers. As knowledge of this possible threat has become more widespread, feed broadcasters have taken the extra precaution of transmitting using the HTTPS protocol over a Secure Socket Layer (SSL). While it's definitely a big step in the right direction, it does place some extra burden on the WordPress site owner, who must now contend with deciphering the digital SSL certificates. In today's article, we'll go over the steps required to subscribe to a secure Atom feed using PHP's cURL utility.

    RSS versus Atom

    RSS 2.0 is the most widely utilized feed format right now. It's not only a lot older than Atom, but it's also used extensively within WordPress. Longevity aside, it isn't without drawbacks. For example, it only supports plain text or escaped HTML content, with no way to indicate which of the two is being served. Moreover, RSS has only three required fields for each item: title, link and description. There are however a variety of optional fields.
    Atom is a more recent specification that is much more robust and feature-rich than RSS. It also introduces the auto-discovery feature. That allows browsers to bring up the feed contents without any additional plugins, either by pointing directly to the feed's URL or to a site that contains one or more feeds.

    Initializing the cURL Library

    cUrl is PHP's Client URL Library. It was created by Daniel Stenberg, and allows you to connect to servers a variety of protocols, including HTTP, HTTPS, ftp, gopher, telnet, dict, file, and ldap. WordPress makes the cURL library available via the rss.php file. Therefore, you must include it in your page.
    Coding with JRebel: Java Forever Changed
    The cURL object is instantiated by calling the curl_init() function. That object is then passed to the curl_setopt() method to set various options, the most important being the URL.
    include_once(ABSPATH.WPINC.'/rss.php');
    
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL, 'https://afictionalsite.com/Feed.aspx?FeedName=TheGoodNewsFirst');
    curl_setopt($ch,CURLOPT_TIMEOUT,60);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    

    Fetching and Reading Feed Contents

    Passing the cURL object to the curl_exec() method retrieves the feed content as an XML-formatted string.

    A Sample Atom Feed
    <?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
    
     <title>Example Feed</title>
     <link href="http://example.org/"/>
     <updated>2003-12-13T18:30:02Z</updated>
     <author>
       <name>John Doe</name>
     </author>
     <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
    
     <entry>
       <title>Atom-Powered Robots Run Amok</title>
       <link href="http://example.org/2003/12/13/atom03"/>
       <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
       <updated>2003-12-13T18:30:02Z</updated>
       <summary>Some text.</summary>
     </entry>
    
    </feed>
    
    To extract data from the feed and present it in a more readable format, the string should be converted into a SimpleXMLElement either by calling the simplexml_load_string() method or by invoking its constructor directly. The SimpleXMLElement implements the Traversable interface so you can iterate over every item using a for each loop.
    // Execute, grab errors
    $result = curl_exec($ch);
    if(!empty($result)) {
      $categoriesfeedXml = new SimpleXMLElement($result, LIBXML_NOCDATA);
      //fetch the products for each category
      if (isset($categoriesfeedXml->entry) ) {
        foreach($feedXml->entry as $entry) {
          //proceess each item
        }
      }
    }
    
    The LIBXML_NOCDATA argument above tells the parser to extract values from <![CDATA[]]> tags.

    Obtaining Certificate Data

    The code presented thus far is only adequate for non-secured feeds over HTTP. Attempting to read a secure feed will result in an error similar to "curl: (60) SSL certificate problem, verify that the CA cert is OK." For that you'll need a copy of the signing authorities' public encryption keys. Here's how to obtain that information using Google Chrome:
         1. Click on the padlock in the address bar to bring up the certificate information.

            2. The certificate dialog will contain a lot of information on the certificate. For instance, the Certificate Path tab is where you'll find the certificate chain from the global authority on down. From there you can view each certificate in turn.

         3. On the Details tab, there is a button with the label "Copy to file...". Click it to bring up the Certificate Export Wizard.
         4. Click the Next button to view the available output formats. Select the Base-64 encoded X.509 (.CER) and click Next.
         5. On the following screen, use the Browse... button to choose a destination folder and give the file a name.
         6. The final screen, entitled "Completing the Export Wizard", displays all of your selected options for you to verify. Once you're satisfied with everything, click the Finish button to export the certificate.
         7. Use your favorite text editor to view the certificate. It will look something like:
    -----BEGIN CERTIFICATE-----
    MIIFBTCCA+2gAwIBAgIDAkhXMA0GCSqGSIb3DQEBBQUAMEAxCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5HZW9UcnVzdCwgSW5jLjEYMBYGA1UEAxMPR2VvVHJ1c3QgU1NM ... EpeV50e01SFVijVL/xPxDisH71ki7oHMA0TB3aqpIxB4AzDbX1gYeAD6FopOYHEs wlV3ubs0xVzMHGjpM599jIPNHv+UPVn+7ZWRcLlsxyTyhlhXkiPIs+OQWumu0lFi yZzqjwmZr1tSneOK/IFKQP4wwNipce3Vt+EY2g9wUKY7jagwJPRxzf32ilL9rHy+ CEWJg2hYmpbvoVWkPvUoM5+rWVwSXpQ2BjbpHeH7J8iU6aorM1lzaciwXlxzyJJj 4QUj8vUG6r5/E3oKNqLh95i6W4NVJg5gbcEdTXT8Vkdg0wkiPXDFYE8=
    -----END CERTIFICATE----
         8. Note that the exported certificate was only the selected one on the Certificate Path tab. You have to follow the above steps to export each certificate in the path. In this particular example, there are two: GeoTrust SSL CA and GeoTrust Global CA.
         9. Now that you've got the entire certificate chain, they need to be amalgamated into one .crt file. Start with the lowest-level one and paste them one-after-the-other, working back to the global certificate authority. Hence, it will be at the bottom of the file. Include everything, including the BEGIN and END CERTIFICATE lines.
         10. Upload it to your host so that cURL can authenticate the feed provider.
         11. Here are the settings that you'll need to add for cURL. That last one is especially important because it points to the location of the .crt file.
    $certfile = ABSPATH.WPINC . '/pret_chain.crt';
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, true); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch,CURLOPT_CAINFO, $certfile);
    

    Conclusion

    Today we learned how to subscribe to a secure Atom feed using PHP's cURL utility and how to obtain the certificate information required to decrypt the feed contents. In the next article, we'll be exploring the Atom format in more depth and how to navigate the feed's XML Document Object Model(DOM).

    Popular Posts

    Contact Form

    Name

    Email *

    Message *