jsus.is-a-geek.org

Code, Code, Revolution!

Crawl cookie protected content with GSA

The GSA (Google Search Appliance) has support for forms based authentication but there are situations when configuring the authentication through the administration panel won’t work. A situation like that could be that you have an intranet or extranet with forms based authentication (such as EPiServer) but the authentication is acutally done by a third party (SSO). In this particular case it’s our own SAML-SSO service that authenticate the user on behalf of the intranet.

HTTPHeaders to the rescue!

The HTTPHeaders setting in GSA administration can be used to send an authentication cookie to the server being crawled. To use this setting you first need to get your dirty hands on a valid cookie value. The easiest way to find a valid cookie value is to set up a temporary page on the site to be crawled that when visited sets a persistent cookie for the GSA crawler account. Point your Firefox browser to that page and view cookies for the domain (Page info -> Security -> View cookies). Enter the cookie name and value into the HTTPHeaders setting in GSA in the following format: Cookie:cookiename=cookievalue.

gsa httpheader setting

This GSA is set to swedish language but if you’re familillar with GSA you’ll understand. I blurred out some info for security reasons.

It’s very important that you understand the security implication. This setting is global, meaning the cookie will be sent to all sites indexed by the GSA. In ASP.NET the password for a user is never stored in the authentication ticket/cookie so it’s not a big deal IF you can restrict access to your protected site by IP per account. In EPiServer 4.x (not possible in EPiServer CMS 5+) this is not a problem, you’re not getting in even through you have the correct cookie if you’re not from the defined IP. If you’re only indexing sites you trust however (ie. internal resources), this is of little or no concern.

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

Avantime and Svenskfast joins the war on terror (IE6)

The war on terror, or Internet Explorer 6, started in our neighboring country: Norway. For once they’ve actually come up with something good and it caught on. Wired wrote about it yesterday, Swedens largest news site Aftonbladet and the largest IT site IDG.se added the IE6 warning today. This of course was something we discussed at work along with the Piratebay trial. I think we can all agree that IE6 comes pretty close after war, religion and toilets that won’t flush on our “things we dislike”-list. Of course we wanted to do our part and help this war on terror and fortunately for us Gunilla Matsson from Svenskfast.se was at our office. We quickly explained what the IE6 warning was all about and she wanted Svensk Fastighetsförmedling to be a part of it too. Not only is it a great cause, it’s also great for publicity! Svenskfast.se is Swedens ~30th most visited site.

To join the war, go to jardenberg.se and get your own warning snippet. Read more about it on mindpark.se, Wired, the site where it all started finn.no and Microsoft Norway is positive to the campaign.

I promise to post statistics on the effect of this campaign in a week or so. Let’s hope the rest of the world joins the war too!

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

EPiServer editor context menu plugin

Last week I was investigating the editor plugin capabilities of EPiServer CMS R2. My goal was to plug into the context menu with my own submenu, you know the kind of menu item that opens another list of options. The lack of documentation in the SDK and elsewhere made the task a bigger headache than it should have. So here’s an example of how to create a context menu item with a submenu, or subitems if you like.

submenu

First we need a “root” item from our context menu. The plugin attribute has the parameter “SubMenuName”, the name we enter here is important to the subitems.

    [EditorPlugIn(Usage = ToolUsage.ContextMenu,
        DisplayName = "ImageAlign",
        SubMenuName = "ImageAlign",
        LanguageKey = "imagealignroot",
        MenuGroup = "CssFormatParagraph")]
    public class AlignImagePlugin : ToolBase, IInitializableTool
    {
        void IInitializableTool.Initialize(HtmlEditor editor)
        {
            // Set the script that check if the menu item is enabled
            ClientSideEnabled = "IsAlignImageAllowed(this)";
        }
    }

To create the subitems use the name we gave the “SubMenuName” parameter for our parent menu item for the “MenuName”. Other than that you go about implementing the subitem just as you would a normal context menu item.

    [EditorPlugIn(Usage = ToolUsage.ContextMenu,
        DisplayName = "Align left",
        MenuName = "ImageAlign",
        LanguageKey = "imagealignleft",
        MenuIndex = 0)]
    public class AlignImageLeftPlugin : ToolBase, IInitializableTool
    {
        void IInitializableTool.Initialize(HtmlEditor editor)
        {
            ClientSideOnClick = string.Format("AlignImage('{0}', 'left');", editor.ClientID);
        }
    }

To make the plugin easy to distribute and deploy, embed the javascript into the dll and register it on the page like this in the root menu item:

        /// CreateChildControls because Page is null in Initialize and we want to register the
        /// javascript file.
        ///
        protected override void CreateChildControls()
        {
            if (Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "CMSEDITOR_ImageAlign") == false)
            {
                Page.ClientScript.RegisterClientScriptInclude("CMSEDITOR_ImageAlign",
                             Page.ClientScript.GetWebResourceUrl(this.GetType(), "CMSEditorPlugin.Editor.Javascript.AlignImage.js"));
            }
 
            base.CreateChildControls();
        }

Good luck on creating your editor plugins! Here’s the full demo project. The project format is Visual Studio 2008.

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

shouldAutorotateToInterfaceOrientation?

This post is something I’ve worked on for quite a while. One of the biggest challenges building HittaHem was the photo-mode. I wanted the images in full screen and of course I wanted the images to rotate as the iPhone was rotated. At first this seemed like a piece of cake, just return YES to the shouldAutorotateToInterfaceOrientation event! Sure, that does it, but I didn’t want the whole application to rotate because the rest of the UI didn’t look good that way.

borat_high_five

Instead of redesigning the entire application just to support rotating images I decided to solve the problem myself. I’ve seen other people ask how to accomplish this on other blogs etc so I know I’m not the only stupid person who thinks it’s a good idea to only rotate a part of the application. I did ask the Italian evangelist person at the iPhone Tech Talk World Tour if there really wasn’t an easier way to do it, his response was “why would you want to do that?”. I tried to explain but apparently it didn’t make sense to him. At least I knew I wasn’t a complete fool investing hours on rewriting something that could be done with one line of code. Facebook rotates the images in the albums without rotating the entire app, and Facebooks (as my mom calls it), can’t be idiots, right?

Instead of pasting tons of code here I’ll try to explain my solution and the biggest problems implementing it. As usual you’ll find a complete demo project at the end of the post.

The easiest way to know if the device is rotated is to listen to the shouldAutorotateToInterfaceOrientation event. But instead of returning YES and rotate the entire app, I forward the event to the superview before returning NO. The superview, in this case the image gallery, can then decide how to rotate its content to fit the new orientation. I place all my images inside a UIScrollView using the PageControl code from Apple. So what happens when the device is rotated? This image is very important:

iPhone orientations

It shows origo (or 0,0) position on the screen in UIInterfaceOrientationLandscapeRight, UIInterfaceOrientationPortrait and UIInterfaceOrientationLandscapeLeft.

Portrait mode
The images are positioned next to each other following the x-axis. The width of the content in the UIScrollView equals the width of one image multiplied by the number of images. So if we have 6 images the contentSize of the UIScrollView is the same height as the screen and the width is 6 times the width of the screen. Height=480 Width=(320*6)=1920. The position of the leftmost image is 0,0.

UIInterfaceOrientationLandscapeRight
LandscapeRight is the “easy” rotation because the images are positioned almost like portrait mode, the difference being they are positioned over the y-axis instead of x. Again if we have 6 images the contentSize of the UIScrollView is the same height as the screen width and the width is 6 times the height of the screen. Height=320 Width=(480*6)=2880. The position of the leftmost image is 0,0.

UIInterfaceOrientationLandscapeLeft
This is where it gets a bit tricky. Because we still want the images positioned from left to right and the 0,0 point is now in the top right corner. If we were to position the images following the y-axis as in LandscapeRight the image positions would be reversed. The first image must be positioned at the highest y-axis value. Same example with 6 images: The leftmost image will be positioned at the screen width multiplied by 5, X=0 Y=5*480. The rightmost image is positioned at 0,0.

Here’s the code to calculate the correct position:

-(CGRect)calculateFramePosition:(CGRect)frame page:(int)page
{
	// Calculate frame position depending on the interface orientation
	if(currentOrientation == UIInterfaceOrientationLandscapeLeft)
	{
		frame.origin.x = 0;
		frame.origin.y = frame.size.height * ([self.viewControllers count]-1 - page);
	}
	else if(currentOrientation == UIInterfaceOrientationLandscapeRight)
	{
		frame.origin.x = 0;
		frame.origin.y = frame.size.height * page;
	}
	else
	{
		frame.origin.x = frame.size.width * page;
		frame.origin.y = 0;
	}
	return frame;
}

The actual rotations are done by the UIView inside the UIScrollView. The view inside the scrollview just holds an UIImage that I’ve subclassed to support taps. The rotations are simple PI rotations using CGAffineTransformMakeRotation. Code:

-(void)rotate:(CGFloat)angle
{
	portraitImageView.transform = CGAffineTransformMakeRotation(angle);
 
	CGRect frame = portraitImageView.frame;
	frame.origin.y = 0;
	frame.origin.x = 0;
	frame.size.width = portraitImageView.frame.size.height;
	frame.size.height = portraitImageView.frame.size.width;
	portraitImageView.frame = frame;
}

Here’s a video of the demo application. It’s using static images bundled with the app and can easily be changed to download images from the internet. Check out my post on downloading images asynchronously. I’ve done my best to add useful comments along with the code but if you have questions don’t hesitate to post a comment below. The code is free to use as you see fit, the only thing I ask is that you don’t publish it as your own and if you found it usefull: add a link to this blog from your site.

Download example project

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

HittaHem - A great success!

Borat thinks HittaHem is a great success
Great success!
HittaHem is nr1 on AppStore

HittaHem was launched a week ago and it was a great success! It took just over 24 hours to become the most popular free application on the Swedish AppStore both in the Lifestyle category and overall. The application was praised and mention on many of Sweden’s largest sites. Here’s a list of sites that wrote about the application (Swedish language warning!)

Dagens Nyheter Resumé
MacWorld Mobil.feber.se
OhSoHighTech.se Mobila affärer
Telia Iphone-blog OmiPhone.se #1
OmiPhone.se #2 NewApps.se
Iconvert Niclas Strahner
Slowmove Newsdesk
Avantime.se Edenström
iLove Robert Macli
MacPro Andreas K
Silverbakk Webbstatistiksystem
Prylkoll & Mobilkoll TeknikFreak
ReklamIT

On top of that, the video of the application was the most watched/popular video on YouTube Sweden! HittaHem maintained it’s position as the most downloaded free app on AppStore Sweden for almost a whole week. Today it fell one place to nr2. Which brings us to something interesting that very few developers share, “How many downloads does it take to reach the most downloaded spot?”, I’ll give you the numbers!

Date Downloads Position
2009-01-19 45 ?
2009-01-20 38 ?
2009-01-21 64 ?
2009-01-22 1 008 2
2009-01-23 1 569 1
2009-01-24 1 008 1
2009-01-25
877
1
2009-01-26 587 1
2009-01-27 404 2

Note that these numbers are for the given time period, for a free application, on the swedish AppStore. Numbers could and will differ between dates, localized store etc, but it gives you an idea of what it takes to reach the nr1 spot on the swedish AppStore.

All of this was made possible because of Svensk Fastighetsförmedlings strong brand and the impressive work by my collegues at Iconvert. A big thank you goes to all the sites who wrote about the application and included the YouTube video!

Find out more about the application @ Svensk Fastighetsförmedling

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

Hitta hem is officially launched!

There’s a YouTube video of the application I’ve developed together with my long time friend Hampus Nilsson for Svensk Fastighetsförmedling.


Hitta hem on YouTube

Download the app here.

*NOTE* Yes, that is my iPhone in the video. Some comments on YouTube implies that it’s an unlocked/hacked iPhone because Telia is not the carrier. This is not the case. It’s an original untouched iPhone 3g 16gb bought in Italy this summer (in Trieste to be exact). iPhones are sold without contracts in Italy and Hampus and  I were lucky enough to score 3 phones from TIM. To be honest we discussed the Telenor carrier logo before the videoshoot and decided to keep it just to create some rumors and more buzz on the blogs etc. My iPod Touch however, is PWND!

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

Debugging ImageVault

ImageVault

You’re having problems with ImageVault and can’t really understand why, ImageVault can tell you what’s up! The most common problem when ImageVault images are broken or doesn’t resize etc is because of user rights on the Data folder where ImageVault reads and writes images. A tool you can’t live without as a web developer is Filemon from SysInternals (now bought by Microsoft), it will tell you if access rights is the problem. But if you’re still having problems or perhaps something else inside ImageVault isn’t working the way it should there’s an undocumented web.config setting that enables debug output to a text file. I don’t really understand why this setting is never mentioned in the SDK or anywhere else for that matter. I found it a while ago through Reflector (now bought by RedGate but still available in a free version), another tool you just can’t live without! Reflector can disassemble a compiled .NET dll or exe and show the real code behind it unless it’s obfuscated.

This is how you enable debug output from ImageVault:

  • Create a folder to hold the output text file and make sure your application pool user can read/write files in it. Create the output file in the folder aswell, it seems ImageVault doesn’t create it if it doesn’t exist. Of course the file must also be read/writeable by the application pool user.
  • Add this key to your ImageVault config in web.config: DebugErrorLog=”c:\pathtologfolder\logfile.txt”. Example:
    <imageVault DebugErrorLog=”c:\Inetpub\mysite\ImageStoreNET\Data\iv.log” ImagePathOriginal=”c:\Inetpub\mysite\ImageStoreNET\Data\ImageDB” ShoppingOrderPath=”c:\Inetpub\mysite\ImageStoreNET\Data\Orders” AdminGroups=”ImageVault Admins” EditorGroups=”ImageVault Editors” ImageVaultConnStr=”Server=sqlserver;Database=iv_database;UID=user;password=password;” />

Now perform whatever steps to produce the problem and check the errorfile to get a clue about what’s wrong. If you still can’t solve the problem now it’s time to contact Meridium for expert help, they are usually very good at helping out and provide workarounds or implement a feature that you need in a future version.

Avantime has been working with ImageVault for 4+ years for a number of customers and run the largest(?!) existing ImageVault implementation at Electrolux for their Intranet.

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

Release of my first iPhone app! Hitta hem (Svensk Fastighetsförmedling)

It’s finally live!! The reason I started this blog and the source of much of the iPhone code I’ve published is finally available on iTunes App Store! I’ve been working on an app which uses the location service to locate the device and then find real estate for sale nearby. Svensk Fastighetsförmedling is one of Swedens largest real estate agent and I already build their website (www.svenskfast.se), their intranet and their sharepoint application portal. It all started out as a research project this late summer after a trip to Italy where Hampus and I bought our iPhones (they are sim unlocked in Italy). We wanted to see what the iPhone was capable of and making a location aware internet app came natural to us. The result is “Hitta hem”. You will find it on iTunes store here: http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=301719769&mt=8

It’s only usable in Sweden because Svensk Fastighetsförmedling only work in Sweden. Here’s some screen shots from the app:

The search result shows how far away the real estate is. The details page has more details including a textual summary of the apartment/house for sale. Through the buttons you can immediately contact the real estate agent using mail or phone. You can also get more pictures (supports orientation) and get directions using Google maps.

The application has been complete for quite some time but legal papers selling the app, Christmas and one rejection has gotten in the way until now. I am very proud of the application. I hope you like it!

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

EPiServer CMS 5 Certified!

EPiServer

I passed the certification for EPiServer CMS 5 this week together with my colleague Mikael Jönsson. Micke and I were already certified for EPiServer 4.31 since three years ago and were surprised to hear that a certification from EPiServer is only valid for two years(!). Our employer Avantime has premium partner status with EPiServer but was now close to loosing it because our certifications were no longer valid to maintain the status. I did keep my certification number of 161 though :).

Some people have stated on their blogs etc that the new certification test is much harder than before and almost “too hard”. In my opinion that’s not true, at least compared to the old test for 4.31. The questions for the CMS 5 test are much more logical and developer oriented. I remember the old test for 4.31 had a questions like “which year was Elektropost AB (now EPiServer AB) founded”, it’s been three years and I’ve never felt like that’s something I really need to know in order to successfully build websites. The test consist of 68 questsions and you only need to answer 60% correctly which is 5 percent less than the test for 4.60 and if i remember correctly the test for 4.31 required 70%. I’ve been working with EPiServer for a reasonable long time but because I’m tied up with many of Avantimes largest customers I havn’t had a chance to write much code for CMS 5, it’s actually just the last 2 few days before christmas until now (about 2 weeks) that I’ve built a complete site in CMS 5. But of course it’s much easier to pass the test if you have much experience with the EPiServer platform.

Fredrik Haglund has some good pointers on his blog to what you should focus on for taking the test. I would like to add that there are questions on some of the functions you would rarely use, depending on your clients of course, like mirroring, configuring enterprise installations with multiple sites, indexing service for search and load balancing. If you’re new to EPiServer there’s a big chance you’ve never touched those type of settings.

I wish you good luck if you’re attempting to get certified! And don’t forget to snatch some of the EPiServer stickers etc from their reception desk when you visit them, they look great on your laptop :).

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]

iPhone flight mode detection with code?!

Turn off flight mode

I just got my (fist) app rejected for App Store by Apple because it relies heavily on the internet connection being available and I didn’t have an information screen about the iPhone being in flight mode so the application wouldn’t do much. In my opinion only an idiot wouldn’t understand that an internet application wasn’t going to work with everything shut down but fair enough, i started hunting for code to detect flight mode.

Of course the developer pages Apple provide doesn’t give any hints. There’s an example on how to check which type of connection was available and that way I did implement an alert informing the user that they had to disable flight mode. But I couldn’t find a way to make the alert as sexy as Safari, with a button to open settings directly in the alert. It reads: “Turn off Airplane Mode or use Wi-Fi to access data”. After lots of searching Google I found out that to get the sexy Safari style alert you don’t need to write any code at all! It’s as simple as adding a property named “SBUsesNetwork” in the plist file for my app and the alert comes up automatically when the application launches. Here’s a screenshot of the plist setting:

SBUsesNetwork plist setting
It should be of type Boolean.

Bookmark / Share:  
[del.icio.us] [Digg] [Facebook] [Google] [Reddit] [StumbleUpon] [Technorati] [Windows Live] [Yahoo!]
U comment, I follow