Friday, February 3, 2012

Working notes Feb. 3, 2012

I am so thankful to be able to work from my home office on occasion. I can create the ideal atmosphere for maximum productivity. That's where I am today, and things are coming together nicely so far.

Today, I am working on integrating an Elgg social network installation with a custom-built PHP/JS/jQuery/MySQL site for a continent-wide, and potentially worldwide, research project.

Step 1 is to get the main site to check the user's login status in the Elgg site. Being logged into Elgg will open access to multiple tools not available to the public.

Based on example code provided by Steve Clay, I have been able to access the Elgg session data for a user and return a string to tell the user they are logged in.

<?php
/*require a PHP PDO database instance here */

$elggstatus=$_COOKIE["Elgg"]; //capture the session ID

if($elggstatus)
    {
    $user_id = 0;
    $sql = ("SELECT `data` FROM `elgg_users_sessions` WHERE `session` = :sessVal");
    $params=array("sessVal"=>$elggstatus);
   
    $elggUser=$thePDO->thePDOselectfunction($sql,$params);
   
    $userData=$elggUser[(dissect your PDO data structure here)];

        $userData=explode('attributes";', $userData); //split the user object after the attributes segment

        $userData=unserialize($userData[1]); //use PHP's unserialize() function to convert the data back to a PHP value
                      
        $userDisplayName=$userData["name"]; //capture the user's "display name"
    print "You are logged in as $displayName";//provide the feedback to the user.
    }
?>
Update 12:00
I sure enjoy these rare occasions when everything falls into place.  Since my original posting I have been able to create a PHP class to communicate with Elgg and return user status and data.  By using this method I'll be able to extend the communication between Elgg and the main site as needed in the future.

It took a little while to get past some bumps in establishing a new PHP PDO MySQL class separate from the primary instance used for the other database, but once that was fixed it works fine.  The next step is to make sure this works regardless of which URL option the user chooses to access the site. (There is a subdomain that goes directly to it, or they can use a long URL including the primary domain + directory tree)

Update 14:25
No real surprise, what I thought was working earlier failed upon testing by a user.  Evidently Elgg returned the user object in a different order for different users, so the code I had posted earlier did not work.  I revisited Steve's example, found where I had taken a wrong turn, and revised my code. Now it accurately converts the stored value into a standard PHP array for easy and consistent parsing.  The code above has been edited to show my corrections.

Next goal: make Elgg write its session cookies so that it can be read from other subdomains.

Update 15:35
Since the last update, I have been working on trying to make the session cookie visible regardless of subdomain. No success.

I tried creating a new php.ini file in the Elgg root directory with this line:
session.cookie_domain=.mydomain.org
and logged in. My browser's cookie library showed that Elgg did properly set the cookie to be owned by .mydomain.com instead of mydomain.com as previously.

However, login now fails totally. When I try to log in, Elgg shows a red bar in the upper right corner saying 'you have to be logged in to see this file.' I had to disable my php.ini file to get my site back.

Back to researching...

Update 17:30
The joys of software architecture... nothing to show for the past 3 hours of work. I detailed my work to get a solution for cookie visibility across subdomains in a post on the Elgg community. With an immovable deadline looming and having lost 3 hours to fruitless research on the problem, I am considering changing the entire installation configuration to minimize the chance of problems. I had hoped to build Elgg into a multisite-capable system, since we have at least 5 different projects that could utilize its social networking functionality. Given that development of the multisite plugin appears to be inactive, I'll probably have to reconfigure my system to reside completely within a single subdomain to avoid these cookie issues. Maybe in the future a multi-site version of Elgg will be viable and I will reconfigure at that point in time.

Thursday, January 26, 2012

Wednesday, January 25, 2012

Useful URLs for today

Today I am working on forms. My goal is to have forms in the current project look cleaner and more modern than default HTML. 

The base I am building from:
http://line25.com/tutorials/create-a-stylish-contact-form-with-html5-css3

How to make form elements float into the same line instead of vertically stacked:
http://stackoverflow.com/questions/2306117/radio-buttons-and-label-to-display-in-same-line

A good toolset for building HTML5 +CSS + JS forms
www.reformedapp.com/

This appears to be a promising tool for creating tree controls in HTML5+jQuery
http://www.jstree.com

Some tips on styling HTML dropdowns using only CSS:
http://stackoverflow.com/questions/1895476/how-to-style-select-dropdown-with-css-only-without-javascript

Saturday, January 21, 2012

Ultimate Waterfowler's Journal registration codes and instructions

In 2000, I created software called Ultimate Waterfowler's Journal.  I no longer am able to support the software, but I know some people out there are still using it.  Due to the registration system built into UWJ, if you upgrade your computer, UWJ will require reregistration. Without my business website online, that is not possible. 


Since UWJ should work with all versions of Windows including 7, anyone with a UWJ installation disc can keep their journals going by using the information below.  I have heard rumors that whatever version of Windows replaces Win7 will no longer support the architecture that Ultimate Waterfowler's Journal was built on. So, print out your journals while it still works.


STEP 1:
Registration keys:
The 5-character code on the left is what UWJ displays for you to enter into the registration system. The right column contains the key that you need to enter into UWJ to satisfy the registration requirement. So, locate the correct code in the left column below, copy the value out of the right column of the same row, and that will be the key you need:

 
A1JFY SEG0V7U
A1LOO 4BIPN5I
B5XLR MJK2BGY
C4JME QO18QNK
D2QVM J3TFL2W
D7LTP 2CDID0N
E5YGX Q5XOGW1
F3KHN Y5X6LRC
F6NFZ 4HT8VED
F8PTX CQ49DXQ
G6MRW HE5GPJW
G9VLM KFIKE6C
H1EQK IQ2F5CL
H3AHZ PHN7V1O
H3VVP GRZGN19
H6GCB HG4GJ0M
I4OUO J5JNLOB
J1MFZ 35XNKVV
J4YDQ F14YOMY
J9WBY TB54HQQ
K1LRM ZP5PCF3
K4MFI E8CL2WT
L7GJK PF18DQX
M1DEB OFM77KX
M2RTP U2YCC7J
O2YXZ UZ2ER0I
P3KWP IWG2EJ0
Q5VCF JES85CT
R0ODD BH3IY9K
R1DHK HU33KVK
R6ZIM EL5U5LN
R8WKD RKAEE54
S5OHI 7USBK8U
S6KYQ P7L8HRW
T1QSA HZ76KSH
T6MEG BN7UI9U
T8HSK LCKI63U
U4FPX ARYA9C3
X2UJH QLCO6X8
X7OLS 27YJRUB



STEP 2:


Customer ID:
You can make up your own customer ID. It is just the state abbreviation + first 4 characters of your last name + 4 digits of todays date + a random letter. Example: Joe Smith in Texas on Sept. 1 would be "TXSMIT0901X"

Pet peeve: Wasteful packaging

Why is it so many companies use huge boxes to display and ship tiny products? Such wastefulness has bothered me for a long time. Recently, I received an order that was just so ridiculous I had to share.

I ordered a tiny HDMI adapter from a popular online store.  A few days later, I received a large box. I was confused at first, since I knew I hadn't ordered anything so large.  Then I opened the box:

Crazy, eh?

Tuesday, January 17, 2012

Work scratchpad for January 17

Today I am continuing my effort to retrieve contents of a Drupal node in an authenticated session. I started by setting up the XMLRPC server in Drupal 7 Services 3.

8:40 a.m. update:
Using the Poster plugin for Firefox, I was able to successfully retrieve a node while logged into Drupal in Firefox by POSTing this to mysite.com/drupal-folder/xmlrpc-endpoint/node/ :

<?xml version="1.0"?>
<methodCall>
 <methodName>node.retrieve</methodName>
 <struct>
  <member>
    <name>nid</name>
    <value><i4>19</i4></value>
   </member>
 </struct>
</methodCall>

And, predictably, when I logged out of Drupal in Firefox, the same POST from Poster was rejected as being from an anonymous user. Good.

I found this valuable comment on StackOverflow:
If you're using Drupal 7 you must be using Services 3 which doesn't have a node.get method (or node.save as it happens). They've been replaced with node.retrieve and node.create & node.update respectively.
Update 9:10

I was able to get a successful XMLRPC login response and user object from Drupal by POSTing this from Firefox Poster:
<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall>
<methodName>user.login</methodName>
<params>
 <param>
  <value>
   <string>example.user</string>
  </value>
 </param>
 <param>
  <value>
   <string>password</string>
  </value>
 </param>
</params> 
</methodCall>

Next step, to capture session auth data and learn how to send it back for the node request.

Update 12:15

So, it turns out that our webhost doesn't support the php_xmlrpc extension on our server. They do provide the PEAR XML_RPC package. Unfortunately, the encoding results are very different and the PEAR-produced object does not seem to be compatible with what Drupal wants. I posted a question about this difference on StackOverflow. Now, back to digging...

Update 13:40

I got a helpful response to my StackOverflow question from mario. He suggested:


To get the XML marshalled output you first construct a message instead, and then use 
the ->serialize()  method:
$msg = new XML_RPC_Message("function", array(new XML_RPC_Value(123, "int")));

print $msg->serialize(); 

I tested that code, and the print result was:

<?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>function</methodName><params><param><value><int>123</int></value></param></params></methodCall>

...exactly what I needed. Now I'll modify the example code into the actual parameters and see what I get.

Update 15:00

I spent lots of time installing PEAR XML_RPC and XML_RPC2 packages and trying to locate and repair their dependencies. No success on version 2, which was the recommended solution.

Using the old XML_RPC package, I can talk to the Drupal server and get my user authenticated. However, I have been unable to parse the server's response. I can see the raw XML it returns if I do a PHP var_dump, but attempts to use the XML_RPC methods fail.  The var_dump shows it is a proper XML_RPC object, but trying to use the ->value() method as used in the example at http://pear.php.net/manual/en/package.webservices.xml-rpc.examples.php results in fatal errors.

Example code from above reference:
if (!$resp->faultCode()) {
$val = $resp->value();
$data = XML_RPC_decode($val);
echo $data[0]['name'] . ' is at version ' . $data[0]['version'];
} else {
/*
* Display problems that have been gracefully cought and
* reported by the xmlrpc.php script
*/
echo 'Fault Code: ' . $resp->faultCode() . "\n";
echo 'Fault Reason: ' . $resp->faultString() . "\n";
}
I get this:
Fatal error: Call to a member function kindOf() on a non-object in /mypath/php/XML/RPC.php on line 1948
 even though the var_dump of $resp shows as:

object(XML_RPC_Response)#4
 Frustrated. I'm going to try another method.