Archive for the ‘Coding’ Category

How to make a text string fit your labels in .NET

March 9, 2009 - 10:43 pm 4 Comments

In my chosen career, I solve problems everyday. Sometimes the problems I’m given are small and simple to solve, and sometimes they are most definitely not. That, I can deal with. What annoys me is when a problem seems like it should only take five or so minutes to solve and yet somehow, it takes you all day. It’s not that you’re bad at what you do, it’s just that the thing you’re trying to do wasn’t quite as simple as you or anyone else had thought it would be. Or perhaps the framework you’re working with has some nasty little quirks that you weren’t aware of. Or perhaps the thing you’re trying to do just hasn’t been done before, or at least hasn’t been well documented. Whatever the reason, spending all day on a “simple problem” isn’t good for your sanity and makes you feel like you ought to be doing COMP101 all over again.

One such problem that I’ve come across more than once in the last few weeks is how to make a text string fit inside a label or other similar control. If the string is too long to fit, the end should be truncated and replaced by an ellipsis. Sounds pretty straightforward eh? Nope, think again.

After coming up with a few complicated solutions including but not limited to iterating through every character in the string and measuring the length of the string (yes, highly inefficient, I know!), I finally found a solution which seems to do the trick. I feel this amazing solution needs to be shared with everyone so here it is:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private string textToDraw = "Hello, how are you? Why does this string not fit in the label that I have drawn? Maybe it is because it is too long?";
 
public Form1()
{
    InitializeComponent();
    label1.Text = ShortenString(textToDraw, this.Width - 10, label1.Font);
}
 
public string ShortenString(string myString, int width, Font font)
{
    string result = string.Copy(myString);
    TextRenderer.MeasureText(result, font, new Size(width, 0), TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString);
 
    return result;
}
 
private void Form1_ResizeEnd(object sender, EventArgs e)
{
    // Set the width to something - I've just set it to the width of the form - 10 to allow for the ellipsis but
    // I guess this would need to depend on which control the label is to be displayed inside of
    int width = this.Width - 10;
    label1.Text = ShortenString(textToDraw, width, label1.Font);
}

The trick to solving this problem was to use the TextRenderer class and calling its MeasureText function. MeasureText doesn’t seem like the most obvious function to use but it seems to work.

Note that this example is for a C# winforms application. The same could be done for a web application although you’d have to use JavaScript to re-calculate the string when the browser or element is resized.

Has anyone else ever had to solve this particular problem? If so, I’m interested to hear how you did it!

  • Share/Bookmark

How to populate a drop down list from an XML file in .NET

February 26, 2009 - 5:48 pm 1 Comment

I know this is not rocket science but it’s actually something I’d never had to do until recently. Normally I populate my drop down lists (and repeaters, etc etc) using data from databases, not XML.

However, fear not. Using XML as a datasource in .NET is super easy. Here is one way to do it:

?View Code CSHARP
1
2
3
4
5
6
7
8
XmlDataSource source = new XmlDataSource();
source.DataFile = Server.MapPath("Values.xml");
source.XPath = "ParentElement/ValueList/ValueItem";
 
myDropDownList.DataSource = source;
myDropDownList.DataTextField = "Text";
myDropDownList.DataValueField = "Value";
myDropDownList.DataBind();

And your xml file, Values.xml, may look something like:

<?xml version="1.0" encoding="utf-8"  standalone="yes" ?>
<ParentElement>
  <ValueList>
    <ValueItem Text="Item 1" Value="1" />
    <ValueItem Text="Item 2" Value="2" />
  </ValueList>
</ParentElement>

Happy coding!

  • Share/Bookmark

How to develop secure .NET applications using Server SSL Certificates and Client Certificates – PART 4

February 25, 2009 - 11:07 pm No Comments

The following article is part 4 and therefore the last in a 4 part series of articles about developing .NET applications using SSL. Part 1 in this series can be found here, part 2 can be found here and part 3 can be found here.


How to set up a web application to automatically redirect to HTTPS if accessed via HTTP when SSL is required

SSL can be “required” at the site level, folder level or even file level.

If any file that has SSL set to “required” is requested via HTTP, HTTP Error 403;4 “Forbidden” will be returned automatically by IIS.  As far as I can tell, there is no simply way to tell IIS to re-direct to the same page via HTTPS.  This effect can be achieved in two different ways and if “defence in depth” is the preferred approach then both solutions can be implemented together.  Note that both solutions require custom code to be written however.


Redirect with IIS and code:

  1. Create a new Web Form (aspx) in your Web Application called RedirectToSSL (or similar).
  2. In the Page_Load event handler, insert the following code:

    ?View Code CSHARP
    1
    2
    3
    4
    5
    6
    7
    8
    
    string redirectUrl = HttpContext.Current.Request.Url.Query; 
    redirectUrl = redirectUrl.Substring((redirectUrl.LastIndexOf(';')+1)    
                     , redirectUrl.Length - (redirectUrl.LastIndexOf(';')+1));
     
    System.UriBuilder secureUrlBuilder = new System.UriBuilder(redirectUrl);
    secureUrlBuilder.Scheme = System.Uri.UriSchemeHttps;
    secureUrlBuilder.Port = -1;    // Use default port 
    HttpContext.Current.Response.Redirect(secureUrlBuilder.Uri.ToString(), true);

  3. The aspx needs to be at least 512 bytes, otherwise IIS won’t redirect to it. So make sure you don’t delete everything out of it, it should never get displayed anyway.
  4. In IIS, right-click your Web Site and go to Properties > Custom Errors.
  5. Select the “403;4” HTTP error in the list HTTP errors and click the Edit Properties button.
  6. Select “URL” from the Message type drop-down list and enter “/RedirectToSSL.aspx” into the URL textbox, as shown below.
  7. Press OK twice to close the dialogs down.
  8. Restart the website and/or reset IIS to ensure all settings have been applied.
  9. Open Internet Explorer and go to: https://<servername>/<securedpage> and verify that you are automatically redirected to the https version of the same page.

Redirect with code alone:
  1. Insert the following code at the beginning of the Page_Load event handler of every page that needs to be secured:

    ?View Code CSHARP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    // Make sure the request has come through SSL (ie that HTTPS has been used)
    if (!HttpContext.Current.Request.IsSecureConnection) {
         System.Uri currentUrl = HttpContext.Current.Request.Url;
         System.UriBuilder secureUrlBuilder = new System.UriBuilder(currentUrl);
     
         secureUrlBuilder.Scheme = System.Uri.UriSchemeHttps;
         secureUrlBuilder.Port = -1;
         HttpContext.Current.Response.Redirect(secureUrlBuilder.Uri.ToString(), true);
    }


      • Share/Bookmark

How to develop secure .NET applications using Server SSL Certificates and Client Certificates – PART 3

February 20, 2009 - 4:43 pm No Comments

The following article is part 3 in a 4 part series of articles about developing .NET applications using SSL. Part 1 in this series can be found here and part 2 can be found here.


Installing Certificates into the correct Certificate Stores

Applications depend heavily on server SSL and client certificates being installed in the correct certificate stores. Certificates may need to be copied and pasted or exported and imported into stores in order to get the systems correctly working together in a secure manner.


Client application (with client certificate):

  1. Local Computer > Trusted Root Authority store should contain the Root CA certificate of the Server SSL Certificate Issuer of the Web application.
  2. Current User > Personal store should contain the Client Certificate for the Client application.
  3. Current User > Trusted Root Authority store should contain the Root CA certificate of the Client Certificate Issuer of the Client application

Web application (with server SSL certificate):
  1. Local Computer > Personal store should contain the Server SSL Certificate for the Web application.
  2. Local Computer > Trusted Root Authority store should contain the Root CA certificate of the Server SSL Certificate Issuer of the Web application.
  3. Local Computer > Trusted Root Authority store should contain the Root CA certificate of the Client Certificate Issuer of the Client application.
  4. Current User > Trusted Root Authority store should contain the Root CA certificate of the Client Certificate Issuer of the Client application.

How to verify the above certificates are in the correct locations:
  1. From the Start menu, select Run, type “mmc” and click OK. This will open the Microsoft Management Console.
  2. Click on the File menu option then on “Add/Remove Snap-in”.
  3. In the Add/Remove Snap-in dialog, click the Add button.
  4. From the Add Standalone Snap-in dialog, select “Certificates” from the list of snap-ins, and click Add.
  5. Select the “Computer account” option and click Add. Select “Local computer” and click Finish.
  6. If you are logged in as the user that will be used to run the client application, add the “My user account” as well.
  7. Now you will be able to look through the Certificates that are installed in all the different stores.
  • Share/Bookmark

How to develop secure .NET applications using Server SSL Certificates and Client Certificates – PART 2

February 19, 2009 - 9:56 pm No Comments

The following article is part 2 in a 4 part series of articles about developing .NET applications using SSL. Part 1 in this series can be found here.


Setting Up Client Certificates

Client certificates can be used to authenticate the client connecting to a web application. The client can either be a browser or a custom written client application.


Requesting a client certificate:

  1. Open IE (Firefox didn’t work so well for me…) and type in: http://<certauthservername>/certsrv/
  2. Click on the “Request a certificate” link.
  3. Click on the “Web Browser Certificate” link.
  4. Enter all required information into the form shown above click “Submit”

Issue the client certificate from your test Certification Authority:
  1. Log onto the Windows Server 2003 machine and open the Certification Authority dialog from Administrative Tools.
  2. Expand the root certification authority “Pending Requests” folder.
  3. The certificate you just requested should be in the “Pending Requests” folder. Right-click on this request and select All Tasks > Issue. The certificate request will be removed from the “Pending Requests” folder and appear in the “Issued Certificates”.

Retrieve the certificate and install it into the Current User > Personal Store:
  1. Go back to IE on your web server and type in http://<certauthservername>/certsrv/ again.
  2. Click on the “View the status of a pending certificate request” link.
  3. Click on the certificate request you want to view.
  4. Click on the “Install this certificate” link.
  5. Click “Yes” on the dialog that opens to install the client certificate.
  6. Click “Yes” on the next dialog as well.

Requiring client certificates at web application with IIS:

Once a client certificate has been requested, issued and installed on a client machine, a web application can be set up to require client certificates.  For extra security, client certificates can also be mapped to a windows account user.
  1. On the client machine, open a Microsoft Management Console with the Certificates snap-in. Export the client certificate without the private key. This will generate a .cer file. Copy this file over to the server hosting the web application.
  2. On the server hosting the web application, right-click the website in IIS and select “Properties”.
  3. Under Properties, go to the “Directory Security” tab.
  4. Under the Secure Communications section, click the “Edit” button.
  5. In the Secure Communications dialog, change the “Client Certificates” option to “Require client certificates” and check the “Enable client certificate mapping” checkbox.
  6. Click on the “Edit” button in the “Enable client certificate mapping” section.
  7. This will open up the Account Mappings dialog.
  8. Click the “Add” button.
  9. Select the client certificate .cer file recently exported from the server that hosts the client application or client browser.
  10. Give the mapping a relevant name and choose the windows user that the web application will be run under.
  11. Click OK.
  12. Click OK to close the Account Mappings dialog and Secure Communications dialogs.
  13. Remove all other authentication options in the IIS manager Directory Security setting by clicking on the “Edit” button under Anonymous access and authentication control in the Directory Security tab.
  14. Uncheck all authentication options and press OK.
  15. Open up a browser and verify that you cannot reach the web site unless you navigate to it from the machine that has the client certificate installed on it.
  • Share/Bookmark

How to develop secure .NET applications using Server SSL Certificates and Client Certificates – PART 1

February 19, 2009 - 12:45 am No Comments

The following article is part 1 in a 4 part series of articles about developing .NET applications using SSL. These articles are based on my experience and I hope that they will help others develop secure applications as well.


Setting up a Development or Test SSL Server Certificate on a Website in IIS (5.0/6.0)

When developing an application that requires SSL you may want a test SSL certificate to develop against.  You can request test SSL certificates from companies such as Verisign however these only last 14 days (and you will be called up by Versign representatives asking you when you would like to buy the real deal).  A much simpler and more flexible solution is to issue your own test SSL and client certificates by setting up a Windows Server 2003 machine that has the Certification Services windows component installed.


First, create an SSL server certificate request:

  1. In IIS, right-click the Upload web site and select “Properties”.
  2. Under Properties, go to the “Directory Security” tab.
  3. Click the “Server Certificate” button and then click Next.
  4. Select the “Create a new certificate” option and click Next.
  5. Select the “Prepare the request now, but send it later” option and click Next.
  6. Go through the next few forms and fill in all required information.
  7. At the end of the wizard you will be asked to save the certificate request as a text file. Do this so you can send this request to a CA later.
  8. You will be shown a summary of your SSL certificate request. Check this thoroughly to make sure you have all the correct values.
  9. Click Next to finish the IIS Certificate Request Wizard.

Then, request a certificate from Certification Authority:
  1. Open IE (Firefox didn’t work so well for me…) and type in: http://<certauthservername>/certsrv/
  2. Click on the “Request a certificate” link.
  3. Click on the “advanced certificate request” link.
  4. Click on the “Submit a certificate request by using a base-64-encoded CMC or PKCS #10 file, or submit a renewal request by using a base-64-encoded PKCS #7 file” link.
  5. Copy and paste the contents of the certificate request generated by IIS (certreq.txt) into the “Saved Request” text box.
  6. Click the “Submit” button to request the certificate

Issue the SSL certificate from your test Certification Authority:
  1. Log onto the Windows Server 2003 machine and open the Certification Authority dialog from Administrative Tools.
  2. Expand the root certification authority “Pending Requests” folder.
  3. The certificate you just requested should be in the “Pending Requests” folder. Right-click on this request and select All Tasks > Issue. The certificate request will be removed from the “Pending Requests” folder and appear in the “Issued Certificates”.

Retrieve the certificate and install it into your website:
  1. Go back to IE on your web server and type in http://<certauthservername>/certsrv/ again.
  2. Click on the “View the status of a pending certificate request” link.
  3. Click on the certificate request you want to view.
  4. Click on the “Download certificate” link. A “File Download” dialog will open. Click Save to save the new SSL certificate as a .cer file.
  5. Go back to the Web Site properties in IIS and from within the Directory Security tab, click on the Server Certificate button.
  6. Select “Process the pending request and install the certificate” and click Next.
  7. Browse to the certificate file saved to disk in step 4 above that contains the SSL certificate issued to this server by your test Certification Authority.
  8. Follow the wizard until the SSL certificate has been successfully installed.

Configure your website to use SSL in IIS:
  1. Once an SSL server certificate has been installed on the website, go back to IIS > > Properties > Directory Security tab > Secure Communications section and click on the “Edit” button.
  2. Check the “Require secure channel (SSL)” checkbox but leave the “Require 128-bit encryption” checkbox empty.
  3. Leave the “Client Certificates” section set to “Ignore client certificates” and the other two checkboxes unchecked for now.
  4. Close this window down and restart the website and/or reset IIS.
  5. Open up a browser and verify that you cannot reach the web site by using http only, instead you must use https.

Finally, you must “trust” the certificate:
  1. If the browser tells you that your certificate was issued by an untrusted CA when you navigate to your website, you will have to download the CA certificate from your test Certification Authority website and install it into the Trusted Root Authority store of the Local Computer.
  2. You may also find that the browser may tell you that the certificate is not valid because it was issued to a different name – that will happen if you are accessing your site using http://localhost/ rather than the server name. The certificate was most likely issued with the actual server name and the browser will think that your site is being spoofed if the domain name in the browser and the certificate don’t match. Use the server name instead.
  • Share/Bookmark

Error message FAIL

August 18, 2008 - 12:10 am No Comments

The other day while on a bus in Brisbane, I witnessed a classic error message FAIL:

Modem FAILED


On a more serious note, error handling and the display of error messages in software development is an often discussed usability topic.  Errors occur for all sorts of reasons – user-generated, hardware failures, invalid data, and of course software bugs.  But how much do you let the end-user know that the software has failed?  Well, I believe it depends on the type of error, the impact of the error and who your audience is.

(more…)
  • Share/Bookmark

Enabling & Disabling ASP.NET radio buttons using code-behind and JavaScript

June 19, 2008 - 12:35 am 5 Comments

I have just come across a strange problem when trying to disable some radio buttons on a web page using .NET and JavaScript. It seems to work well in Firefox but not IE, what a surprise!

The situation:

I have two sets of radio buttons – two RadioButtonList controls. The first set needs to control the second set – that is, when one of the radio buttons in the first set is selected, the other RadioButtonList control should be enabled, and when the other of the radio buttons in the first RadioButtonList control is selected, the second RadioButtonList control should be disabled.

In my code-behind, I had an event handler for the first RadioButtonList control to check if the selected index had changed. If so, check the value of the first RadioButtonList control and if it’s say equal to 1, then set the Enabled property of the second RadioButtonList control to false. Otherwise, set the Enabled property to true.

Obviously this alone doesn’t fix the problem unless the first RadioButtonList control is set to AutoPostBack = True. I needed some code on the client side to do this when while the user wasn’t posting the page back.

The code to disable some radio buttons is simple:

?View Code JAVASCRIPT
1
2
3
4
var secondRadioButtons = document.form1.secondRadioButtonList;
for(var i=0; i<secondRadioButtons.length;i++ ){
    document.form1.secondRadioButtons[i].disabled = false;
}

The problem:

When you wire all this up, it works fine in Firefox… But does it work in IE? No, of course not. So why not? I found that when I first loaded the page, the radio buttons were enabled / disabled as they should have been. Clicking on the first set of radio buttons was disabling / enabling the second RadioButtonList control as it should have. But as soon as I posted the page back (the page had a button that submitted a form and displayed some results), the second RadioButtonList control was completely disabled and no matter which of the first radio buttons I selected, I couldn’t re-enable it. I stuck some debug code in my JavaScript only to find that it was running correctly and firing when it should. As far as I could tell, the JavaScript was setting disabled = false (as above) on all of the radio buttons in the second RadioButtonList control, but they were still disabled. Why!?

I took a look at the source code for the page and noticed something that I thought might have been causing the problem I was experiencing. Basically, browsers renders an asp:RadioButtonList control like this:

1
2
3
4
5
6
<span id="secondRadioButtonList">
<input id="secondRadioButtonList_0" name="secondRadioButtonList" value="1" type="radio" />
    <label for="secondRadioButtonList_0">First radio button</label>
<input id="secondRadioButtonList_1" name="secondRadioButtonList" value="2" type="radio" />
    <label for="secondRadioButtonList_1">Second radio button</label>
</span>

If you disable a RadioButtonList in your code-behind, the same asp:RadioButtonList control will be rendered like this:

1
2
3
4
5
6
7
8
<span id="secondRadioButtonList" disabled="disabled">
    <span disabled="disabled">
<input id="secondRadioButtonList_0" name="secondRadioButtonList" value="1" disabled="disabled" type="radio" />
        <label for="secondRadioButtonList_0">First radio button</label>
<input id="secondRadioButtonList_1" name="secondRadioButtonList" value="2" disabled="disabled" type="radio" />
        <label for="secondRadioButtonList_1">Second radio button</label>
    </span>
</span>

This is precisely why I don’t like asp controls – they look nice in the html that you write yet when they render out to the browser, they’re filled with extra stuff like these two spans.

Anyway, the problem were these spans – obviously even though I was setting ‘disabled = true’ on all the radio buttons inside my asp:RadioButtonList control, there were a couple of spans around the radio buttons that were also disabled causing my radio buttons to appear disabled regardless of their individual status.

The solution:

My solution to this was to simply remove the code-behind that I had written to enable or disable the RadioButtonList control on the server side. My JavaScript is all I really need.

However, if you desperately want or need to have some server-side code also disabling your radio buttons, you should do so like this:

?View Code CSHARP
1
secondRadioButtonList.InputAttributes.Add(”disabled”, “disabled”);

rather than

?View Code CSHARP
1
secondRadioButtonList.Enabled = false;
  • Share/Bookmark

Code for GPS Tracking with Google Maps & AJAX

March 15, 2008 - 4:42 pm No Comments

Over the past few months, my article on GPS Tracking with Google Maps & AJAX has received many hits and attracted a multitude of comments requesting that the code for it be made available. I apologize for the delay but I’ve been away on holiday and far away from my trusted laptop. Now that things are somewhat back to normal and I can spend hour upon hour on my laptop again, here is the code that so many of you have asked for. I hope it makes sense and that it helps you all with what you’re trying to achieve. Obviously I haven’t posted the entire HTML and PHP coz it’s not all relevant to the GPS plotting but I hope what I have posted gives ya’ll a general idea on how to solve this particular problem. I’m sure there are many different ways to do this but this was just one way that I tried.Please feel free to ask questions and I’ll try to answer as best as I can! :)

...

Within the head section of the page that contains the gps tracking map:

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script language="JavaScript">
 
function setTimer() {
   window.setTimeout("show_data();",5000);
}
 
function show_data(){
   //Append the id (just a simple count) to the requestURL
   var requestURL = "http://www.sitename.com/getGpsPoints.php";
   var count = document.getElementById("counter").value;
   count = parseInt(count, 10);
   var queries = "?id=" + count;
   var url = requestURL + queries;
 
   //Increment the hidden counter variable
   document.getElementById("counter").value = count+1; 
 
   var request = GXmlHttp.create();
   request.open("GET", url, true);
 
   request.onreadystatechange = function() {
      if (request.readyState == 4) {
         var xmlDoc = request.responseXML;
         var markers = xmlDoc.documentElement.getElementsByTagName("marker");
 
         for (var i = 0; i < markers.length; i++) {
            var point = new GPoint(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
 
            // Draw the MapMarker
            var mapMarker = new GMarker(point);
            map.addOverlay(mapMarker);
         }
 
         // Recenter the map
         map.centerAtLatLng(point); 
      }
   }
 
   request.send(null);
 
   //Reset the timer so that the page keeps refreshing itself
   setTimer();
}
 
</script>

Within the body section of the page that contains the gps tracking map, right at the bottom just before the /body tag:

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
<script language="JavaScript">
   var query = window.location.pathname;
   if (query == "/mapping/gps-tracking-with-google-maps--ajax") {
      var map = new GMap(document.getElementById("map"));
      mapSetup();
      setTimer();
   }
</script>

Separate PHP script that queries your database to retrieve the GPS points to plot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
    header ("content-type: text/xml");
 
    $link = mysql_connect ("localhost", "username", "password");
    if (!$link) {
        die('Could not connect: ' . mysql_error());
    }
 
    mysql_select_db ("dbname");
 
    //If no search string is passed, then we can't search
    if(empty($_GET["id"])) {
        echo " ";
    } else {
        //Remove whitespace from beginning x%x% end of passed search.
        $search = trim($_GET["id"]);
 
        //Query the DB and store the result in a variable
        $query = mysql_query("SELECT * FROM gps WHERE id=".$search);
 
        //If no rows are found...
        if(mysql_num_rows($query) == 0) {
            echo " ";
        } else {
            //Stick the returned rows into a handy array for easy use
            $row = mysql_fetch_array($query) or die(mysql_error()); 
 
            //Write out XML using values returned by the query
            echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><markers><marker lat=\"".$row["lat"]."\" lng=\"".$row["lng"]."\" /></markers>";
        }
    }
 
    mysql_close($link);
?>
  • Share/Bookmark

Textpattern plugins and Facebook apps

August 12, 2007 - 5:37 pm 4 Comments

Since Chris and I have become addicted to Facebook, we decided it would be cool to have a plugin for our respective blogging engines (Chris uses WordPress, I use Textpattern) that would update our Facebook accounts’ mini-feeds when we posted something on our blogs. Thus we both set off on our epic missions to create Facebook applications and WordPress / Textpattern plugins that would support this behaviour.

Here I’ll relate my experience with my Textpattern plugin. I’ll leave Chris to talk about his experience with WordPress.

So yeah, basically, my experience was a nightmare.

This was my first attempt ever at writing a Textpattern plugin so I am by no means an expert at this. It took me a while to figure out how to compile my php code so that I could deploy it to my Textpattern instance on my web server. Then it took me another while to figure out how to hook into Textpattern ‘events’. I must say, the documentation for this is really poor and I found myself trawling through the Textpattern source to figure out what functions did what. Not pretty. The best (and only) sites I found that helped me somewhat were this article on threshold state and this Textpattern source repository.

When I finally figured out how to call the ‘register_callback’ functions and that I had to use ‘article’ as the event I wanted to register my own events against, I was able to get stuck into it.

My next challenge was how to add a checkbox to the ‘write’ tab of the admin screens. I wanted a checkbox that when checked, would essentially call my code to notify my facebook account of my post. If it wasn’t checked, it wouldn’t notify facebook. However, adding a checkbox and positioning it where ever I want in the flow of elements on the page was NOT an easy task. Below is a sample of the code I had to use to get this to work:

1
2
3
4
5
6
7
8
9
10
function mdt_event_insert_checkbox($buffer) {
   $fb_notify = graf('<small><label for="notify_facebook">'.
      checkbox("notify_facebook", '1', '1', '', 'notify_facebook').
      'Notify Facebook?</label>&nbsp;');
 
   $find = '<input type="submit"';
   $replace = $fb_notify.$find;
 
   return str_replace($find, $replace, $buffer);
}

NASTY! I had to find the ‘Save’ button, then replace the HTML with my new HTML that includes the checkbox. OMG.

Anyway, I finally got that working (see screenshot below).

Next I needed to grab the title of the new post, the friendly-url to the article on my site and the excerpt of the new article. This again was no easy task. The following code seems to do the trick:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function current_url() {
   return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
 
function get_latest_post() {
   include_once txpath.'/publish/taghandlers.php';
 
   // get the latest article posted
   $rs = safe_row("ID, Title, Excerpt", 'textpattern', "1=1 ORDER BY LastMod DESC LIMIT 0,1");
 
   $title = ' has blogged: ' . urlencode(stripslashes(urldecode('<a href="' . permlinkurl_id($rs['ID']) . '">'))) . substr($rs['Title'], 0, 45) . '</a>';
   $msg = substr($rs['Excerpt'], 0, 180);
   $url = current_url();
 
   if (strtolower($step) == "publish") {
   $url = $url . "?event=article";
 
   } elseif (strtolower($step) == "edit") {
      $url = $url . "?event=articlex%x%step=editx%x%ID=" . $rs['ID'];
   }
}

So now the tricky part – how to connect to Facebook, log in as myself and call the Facebook API function that updates my ‘mini-feed’ with some content. I first attempted this by embedding the Facebook API into the Textpattern plugin so that the integration would be completely seamless. This, however, was difficult on many levels. First of all, I couldn’t get the Facebook API to compile into my Textpattern plugin. The php compiler would tell me that certain server variables weren’t defined, etc etc. I did iron out all those error messages and warnings eventually though and finally got the code to compile. However, I later realized that this was never going to be a feasible solution because in order for this to work, my Facebook developers’ API key and secret key would need to be hard-coded into the Textpattern plugin and if I were ever to make this Textpattern plugin public (which I intend to do), I would be sharing my API and secret keys, something I don’t necessarily want to do. Doh! So I had to change my thinking somewhat.

The solution to this was to basically write the Facebook part of the plugin as a totally separate web application and have the Textpattern plugin call this web app, passing through to it the title, url and excerpt in the form of a query string. This method lets the Facebook web application handle all the Facebook functionality (logging in and authenticating, remembering you once you’re logged in, calling the appropriate API functions, etc etc) and the Textpattern plugin basically doesn’t need to know anything about Facebook.

What a mission.

However, it all seems to be working now and I’ve used it once already. Those of you who are on Facebook and have added me as a friend will be able to see little posts on my mini-feed (on my profile page) saying “Annie has blogged…” with a link through to this article. Very cool :) When I am comfortable that things are working as intended and I tidy things up enough to make my Textpattern plugin publicly available, I’ll put it up on my here somewhere for people to grab.

Phew

  • Share/Bookmark