<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>ServiceURLs.plist</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -48,7 +48,9 @@
   NSNetServiceBrowser *metaBrowser;
   NSMutableArray *serviceBrowsers;
   NSMutableArray *hosts;
-	NSMutableArray *serviceTypes;
+  NSMutableArray *serviceTypes;
+  
+  NSDictionary *serviceURLs;
 }
 
 - (void)refreshList;
@@ -59,6 +61,7 @@
 @property (nonatomic, retain) NSMutableArray* hosts;
 @property (nonatomic, retain) NSMutableArray* serviceTypes;
 @property (nonatomic, retain) NSMutableArray* serviceBrowsers;
+@property (nonatomic, retain) NSDictionary* serviceURLs;
 @property NSInteger displayMode;
 @end
 </diff>
      <filename>Classes/FlameTouchAppDelegate.h</filename>
    </modified>
    <modified>
      <diff>@@ -46,6 +46,7 @@
 @synthesize hosts;
 @synthesize serviceTypes;
 @synthesize serviceBrowsers;
+@synthesize serviceURLs;
 
 - (void)applicationDidFinishLaunching:(UIApplication *)application {
   // Start the spinner on a blank app screen to indicate that we're thinking..
@@ -64,6 +65,9 @@
   [metaBrowser setDelegate:self];
   [metaBrowser searchForServicesOfType:@&quot;_services._dns-sd._udp.&quot; inDomain:@&quot;&quot;];
   
+  // set up serviceURLs dictionary
+  self.serviceURLs = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@&quot;ServiceURLs&quot; ofType:@&quot;plist&quot;]];
+  
   // in a couple of seconds, report if we have no wifi
   [self performSelector:@selector(checkWifi) withObject:nil afterDelay:5.0];
   
@@ -267,6 +271,7 @@
   self.serviceBrowsers = nil;
   self.hosts = nil;
   self.serviceTypes = nil;
+  self.serviceURLs = nil;
   [super dealloc];
 }
 </diff>
      <filename>Classes/FlameTouchAppDelegate.m</filename>
    </modified>
    <modified>
      <diff>@@ -30,6 +30,7 @@
 */
 
 #import &quot;NSNetService+FlameExtras.h&quot;
+#import &quot;FlameTouchAppDelegate.h&quot;
 #include &lt;netinet/in.h&gt;
 #include &lt;arpa/inet.h&gt;
 
@@ -143,28 +144,106 @@
   NSString * URLString = nil;
   NSString * myType = [self type];
   
-  if ( [myType isEqualToString:@&quot;_urlbookmark._tcp.&quot;] ) {
+  id protocol = [((FlameTouchAppDelegate*)[[UIApplication sharedApplication] delegate]).serviceURLs objectForKey:myType];
+  
+  if (protocol != nil) {
+    /* 
+     There could be several protocols for a service type. Choose the one to use as follows:
+     1. Use the first service type that can be opened by an application if possible or
+     2. Use the first service type in the list.
+    */
+    NSArray * protocols = nil;
+    if ([protocol isKindOfClass:[NSArray class]]) {
+      protocols = protocol;
+    }
+    else if ([protocol isKindOfClass:[NSString class]]) {
+      protocols = [NSArray arrayWithObject:protocol];
+    }
+    
+    NSString * protocolName = nil;
+    NSInteger defaultPort = 0;
+    for (NSString * myProtocol in protocols) {
+      NSArray * protocolAndPort = [myProtocol componentsSeparatedByString:@&quot;:&quot;];
+      NSString * myProtocol;
+      NSInteger myPort = 0;
+      myProtocol = [protocolAndPort objectAtIndex:0];
+      if ( [protocolAndPort count] &gt; 1 ) {
+        myPort = [[protocolAndPort objectAtIndex:1] integerValue];
+      }
+      NSURL * URL = [NSURL URLWithString:[NSString stringWithFormat:@&quot;%@://localhost&quot;, myProtocol]];
+      if ([[UIApplication sharedApplication] canOpenURL:URL]) {
+        protocolName = myProtocol;
+        defaultPort = myPort;
+        break;
+      }
+    }
+    if (protocolName == nil) {
+      NSArray * protocolAndPort = [[protocols objectAtIndex:0] componentsSeparatedByString:@&quot;:&quot;];
+      protocolName = [protocolAndPort objectAtIndex:0];
+      if ( [protocolAndPort count] &gt; 1 ) {
+        defaultPort = [[protocolAndPort objectAtIndex:1] integerValue];
+      }
+    }
+    
+        
+    /* Create URL with:
+     1. protocol name
+     2. user name and password if available
+     3. host name if possible, otherwise use IP address
+     4. port number if it differs from the default port number for the protocol
+     5. path if available
+    */
+    NSDictionary * TXTRecordDict = [NSNetService dictionaryFromTXTRecordData:[self TXTRecordData]];
+
+    NSString * userAndPassword = @&quot;&quot;;
+    NSData * TXTData = [TXTRecordDict objectForKey:@&quot;u&quot;];
+    if (TXTData != nil) {
+      NSString * userName = [[[NSString alloc] initWithData:TXTData encoding:NSUTF8StringEncoding] autorelease];
+      NSString * password = nil;
+      if (userName != nil) {
+        TXTData = [TXTRecordDict objectForKey:@&quot;p&quot;];
+        if (TXTData != nil) {
+          password = [[[NSString alloc] initWithData:TXTData encoding:NSUTF8StringEncoding] autorelease];
+        }
+        if (password != nil) {
+          userAndPassword = [NSString stringWithFormat:@&quot;%@:%@@&quot;, userName, password];
+        }
+        else {
+          userAndPassword = [NSString stringWithFormat:@&quot;%@@&quot;, userName];
+        }
+      }
+    }
+
+    NSString * hostName = [self hostName];
+    if (hostName == nil) {
+      hostName = self.hostIPString;
+    }
+    
+    NSString * portNumber = @&quot;&quot;;
+    if ([self port] != defaultPort) {
+      portNumber = [NSString stringWithFormat:@&quot;:%i&quot;, [self port]];
+    }
+    
+    NSString * path = @&quot;&quot;;
+    TXTData = [TXTRecordDict objectForKey:@&quot;path&quot;];
+    if (TXTData != nil) {
+      NSString * thePath = [[[NSString alloc] initWithData:TXTData encoding:NSUTF8StringEncoding] autorelease];
+      if (thePath != nil) {
+        path = [NSString stringWithFormat:@&quot;/%@&quot;, thePath];
+      }
+    }
+    
+    URLString = [NSString stringWithFormat:@&quot;%@://%@%@%@%@&quot;, protocolName, userAndPassword, hostName, portNumber, path];
+    
+  }
+  else if ( [myType isEqualToString:@&quot;_urlbookmark._tcp.&quot;] ) {
     NSDictionary * TXTRecordDict = [NSNetService dictionaryFromTXTRecordData:[self TXTRecordData]];
     NSData * URLData = [TXTRecordDict objectForKey:@&quot;URL&quot;];
     if (URLData != nil) {
       URLString = [[[NSString alloc] initWithData:URLData encoding:NSUTF8StringEncoding] autorelease];
     }
-  } 
-  else if ( [myType isEqualToString:@&quot;_http._tcp.&quot;] ) {
-    if ([self port] == 80) {
-      URLString = [NSString stringWithFormat:@&quot;http://%@/&quot;, self.hostIPString];
-    } else {
-      URLString = [NSString stringWithFormat:@&quot;http://%@:%i/&quot;, self.hostIPString, [self port]];
-    }
-  } 
-  else if ( [myType isEqualToString:@&quot;_ssh._tcp.&quot;] ) {
-    if ([self port] == 22) {
-      URLString = [NSString stringWithFormat:@&quot;ssh://%@/&quot;, self.hostIPString];
-    } else {
-      URLString = [NSString stringWithFormat:@&quot;ssh://%@:%i/&quot;, self.hostIPString, [self port]];
-    }
   }
-  
+    
   NSURL * result = nil;
   if (URLString != nil) {
     result = [NSURL URLWithString:URLString];</diff>
      <filename>Classes/NSNetService+FlameExtras.m</filename>
    </modified>
    <modified>
      <diff>@@ -14,6 +14,7 @@
 		2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; };
 		28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C286E00D94DF7D0034E888 /* RootViewController.m */; };
 		6C296B0E1042CF7A00D84978 /* about.css in Resources */ = {isa = PBXBuildFile; fileRef = 6C296B0D1042CF7A00D84978 /* about.css */; };
+		6C2C5CDE1069602900A90A54 /* ServiceURLs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C5CDD1069602900A90A54 /* ServiceURLs.plist */; };
 		6C9CB34C103DBE9400D2FDEA /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; };
 		6CA160131020BCA700ADCEB0 /* ServiceType.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CA160121020BCA700ADCEB0 /* ServiceType.m */; };
 		6CE234C0103C781200DAE0F3 /* ServiceNames.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6CE234BF103C781200DAE0F3 /* ServiceNames.strings */; };
@@ -46,6 +47,7 @@
 		28C286E00D94DF7D0034E888 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = &quot;&lt;group&gt;&quot;; };
 		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = &quot;&lt;group&gt;&quot;; };
 		6C296B0D1042CF7A00D84978 /* about.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = about.css; sourceTree = &quot;&lt;group&gt;&quot;; };
+		6C2C5CDD1069602900A90A54 /* ServiceURLs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ServiceURLs.plist; sourceTree = &quot;&lt;group&gt;&quot;; };
 		6C36437D1040253D00DF2197 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/ServiceNames.strings; sourceTree = &quot;&lt;group&gt;&quot;; };
 		6C9CB30D103DB98A00D2FDEA /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = &quot;&lt;group&gt;&quot;; };
 		6C9CB33A103DBD3900D2FDEA /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = fr; path = fr.lproj/about.html; sourceTree = &quot;&lt;group&gt;&quot;; };
@@ -162,6 +164,7 @@
 				6CE235FD103CAD7400DAE0F3 /* about.html */,
 				6CE235AC103C986600DAE0F3 /* Localizable.strings */,
 				6CE234BF103C781200DAE0F3 /* ServiceNames.strings */,
+				6C2C5CDD1069602900A90A54 /* ServiceURLs.plist */,
 			);
 			name = Resources;
 			sourceTree = &quot;&lt;group&gt;&quot;;
@@ -247,6 +250,7 @@
 				6C296B0E1042CF7A00D84978 /* about.css in Resources */,
 				E6F72701104697B500FAE334 /* flame_square.png in Resources */,
 				E6C626191068D21D00847E99 /* LICENSE in Resources */,
+				6C2C5CDE1069602900A90A54 /* ServiceURLs.plist in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};</diff>
      <filename>FlameTouch.xcodeproj/project.pbxproj</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2b9632139669953d1d449321afc2d00111e1bbc8</id>
    </parent>
  </parents>
  <author>
    <name>ssp</name>
    <email>ssp-web@earthlingsoft.net</email>
  </author>
  <url>http://github.com/jerakeen/flametouch/commit/95ee69b5b5bf0fe78dc5c36d8ae1c77a1dc1da4c</url>
  <id>95ee69b5b5bf0fe78dc5c36d8ae1c77a1dc1da4c</id>
  <committed-date>2009-09-22T14:28:23-07:00</committed-date>
  <authored-date>2009-09-22T14:28:23-07:00</authored-date>
  <message>Generalise URL building for services.

Have a separate file with information about the protocol(s) and default ports associated to each Service Type. Determine the URL to be built from that list and the capabilities of installed applications.

Use the quasi standard u, p and path parameters from the TXT Record to build a full URL rather than just pointing to the host.</message>
  <tree>3b84be0c2e58060c8475a02fd966e17513cdc0da</tree>
  <committer>
    <name>ssp</name>
    <email>ssp-web@earthlingsoft.net</email>
  </committer>
</commit>
