Friday, March 21, 2008

CustomAction and {ListId} token bug : JavaScript to the rescue

This bug is widely blogged. You can checkout entries here

http://chrissyblanco.blogspot.com/2007/12/bug-with-customaction-in-actions-menu.html
http://stephenkaye.blogspot.com/2008/02/bug-with-customactions.html

if you define a CustomAction as part of a feature and use tokens in the URL e.g. , the custom action will work fine in a Lists and Document Libraries . However, if you add a web part representing the same List to another page the tokens in the url do not get replaced.

Solution

I am a big believer in javascript. So here is the Javascript solution. After inspecting the page, it turns out that SharePoint creates a ctx javascript object for the list. This object contains a property listName, which holds the ListId property


1) If the MenuItem is yours and you have luxary to change the feature XML code, you coul
construct your element something like

<UrlActionUrl="javacript:window.location='~site/_layouts/pageaspx?List'+ctx.listName"/>


2) If you are using third party feature or if you have issue with out of the box menuitems, you can insert the following Javascript, either by adding a "Content Editor WebPart" or by modifying the aspx page

var __menus = document.getElementsByTagName('ie:menuitem');
for (var i = 0; i <>
itm = __menus(i)
var str = itm.getAttribute("onMenuClick");
if (str && ctx && str.match('ListId') != null )
{ str = str.replace("ListId", ctx.listName)
itm.setAttribute('onMenuClick', str);
}

This code will replace the {ListId} token on all menus items where token is not replaced.


Note : This solution will only work if you have single list on a page. For multiple lists you need to get hold of "ctx" array object in those cases

Sunday, December 09, 2007

SharePoint designer workflow and Activity Duration report

If you design a workflow from SharePoint designer and try to view the"Activity Duration Report", you are most likely to see the following error









Report contains no data. at Microsoft.Office.RecordsManagement.Reporting.Report.Generate(Hashtable query) at Microsoft.Office.RecordsManagement.Reporting.ApplicationPages.GenerateReport.Generate(String strReportId) at Microsoft.Office.RecordsManagement.Reporting.ApplicationPages.GenerateReport.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint




Workaround

After lot of frustrations and trials and errors, I discovered that this report is only get generated if you have some entries in the hidden "Workflow history" list. The only way to put something int he history list from SharePoint designer is to have a "Log to History" list action item as shown below







The assembly responsible for generating these reports are mostly obfuscated. I have a support ticket open with Microsoft with no luck. So far can not figure out how this report is suppose to be generated and why this report is available for Visual studio generated workflow and NOT for SharePoint designer

If someone know the solution, please send me an email

Friday, November 09, 2007

<CustomAcion>/<UrlAction> and opening a link in a new window

The <customelement> element lets you build a custom menu item for various SharePoint UIs and you can easily deploy your menus using Feature framework.

If you need to include a custom hyper link - You need to use - The problem with is that there is no attribute to open it in a new window - There is no equivalent of "target" attribute of an Anchor - I guess whoever designed this feature must have thought hmmm...since there are lot of pop-blockers who would want to open a hyper link in a new window - So why bother putting this feature :) Well pop-blocker are good for blocking ad windows but at a time you do want to open a link in a new window for usability purpose -

So in order to open a link in a new window you can use the good old javascript:window.open(url)

e.g.

<urlaction url="javascript:window.open('url')" >



What is wrong with the above line ???

Well, the above line works when deployed in SharePoint - The target link in fact does opened in in a new window but while IE opens the link in a new window, it also replaces the current window with [Object] message (IE tries to open the javascript as a link in the current window) - This is pretty annoying - You need to click the back button to go back to the previous screen in the current window...

How to solve the problem in IE ?

Well , you can trick IE to think this is not a window.open() command and you are executing a custom script - So just replace the above url with something like


<urlaction url="javasscript:void window.open('url')">


And now IE will only open the link in a new window -

I hope Microsoft fixes this during SP1 time frame by providing a "target" attribute on UrlAction element




Thursday, September 27, 2007

Content Query WebPart(CopyUtil.aspx) and Anonymous Access on your site

Content Query WebPart (CQWP) is a great little webpart, which lets you display any content from any level of your site on a webpart page. The problem with this webpart is that it was not designed for anonymous access, at least not completely. O.



If you have a site enabled with anonymous access and if you drop this web part on a page. you will notice that this webpart shows the contents to anonymous user correctly however when you click on any of the list item(hyperlink), It will challenge you to enter windows credentials or you will get "403" forbidden error.

After examines I found that Content Query Webpart usages copyutil.aspx page in layouts folder which in turn redirects to appropriate edit form depending on the type of the list. That's where the problem lies.

The "CopyUtil" class inherits from a generic class called "UnsecuredLayoutsPageBase". This class has a property called AllowAnonymousAccess . Which the inheriting class should override and set it to the true or false based on how web application is configured







Workaround:

1) Override the ContentQuery Web Part's XSLT and instead of using copyutils.aspx use the "dispform.aspx"

2) Create a cusotm copyutil.aspx page and override the AllowAnonymous property

Monday, September 17, 2007

FBA and friendly display name in SharePoint 2007

If you have ever implemented the form authentication(FBA) in SharePoint, you will soon experience that SharePoint treats non AD authentication as a step child. Though , its very simple and straight forward to implement a form based authentication however it is not the same user experience as you would expect or see with Active Directory based authentication.

One thing immediately becames visible is the user name. When you log with Active Directory you see a friendly name like shown below.





However , with the form authentication you see the loginId and NOT the FirstName & Last Name, you would like to see.The reason is simple. The standard MembershipUser interface, only has one property called "UserName", This properly holds the fully qualified user name ( domain/username) or (membershipprovider/userId) .
So how do we display a friendly name? After investigating, I came up with two options.
1) User Profile (MOSS Only)
It appears that SharePoint read the friendly display name from the user profile of a user if one exists. By default there is no user profile created for FBA. You can manually create a user profile for all users via SSP or programmatically create for all users.
I found following utility by Sahil , which takes a xml file and does bulk user profile import. Sahils' also shows a code snippet on how to programmatically create user profile

http://blah.winsmarts.com/2007-1-SharePoint_2007_Utility_-2_-_PI_-_Utility_to_Import-Export_actual_user_profiles.aspx
2) UserInfo table (WSS and MOSS)
This solution requires direct update to SharePoint table but does work. So I recommend carefully planning before any update.

At every site collection level, SharePoint stores the firstname + last name in the userInfo table . The friendly name is appears to be picked up from the tp_title column. I believe SharePoint creates entry in this table, the first time you add a user in any list or a site ACL. Look for your form authenticatation (FBA) userId in this table and replace it with a friendly name.

I think this is a good enhancement request for MembershipProvider and SharePoint team

Saturday, September 01, 2007

Microsoft breaking its own rules of cookie security

In order to minimize the XSS vulnarabilites, Microsoft had implemented a "HttpOnly" cookie feature in IE 5.0 and above versions. This feature prevents other scripts or applications (e.g. applets) from directly accessing the cookie marked as "HttpOnly". Fair enough, though not everyone agrees that this really prevents any attack but I think its a good idea. ( http://www.gnucitizen.org/blog/why-httponly-wont-protect-you)


What is the relation of HttpOnly cookies with SharePoint? Well, as you know SharePoint 2007 is a ASP.NET 2.0 application, which means its utilizes all underlying features of ASP.NET 2.0 such as authentication and authorization. When ASP.NET authenticate user via form, it generates a cookie called ".ASPXAUTH" cookie. This cookie by default is marked as httpOnly, which mean no other applications should be able to access this cookie, including windows call such as InternetGetCookie (http://msdn2.microsoft.com/en-us/library/aa384710.aspx) which gets all cookies stored on your computer for a given site but respects the "HttpOnly" flag..

Office applications such as Word, Excel and SharePoint designer does not work well with Form Authentication but you can make it by setting the authentication cookie to persistent cookie. When you set the form authentication, the SharePoint login page has a check box to remember the userId/Password, this creates a persistent cookie, After this setting, if you open the Office applications, you are not prompted for authentication. If the Office applications are playing by rule and using the InternetGetCookie() method to get the cookies for a given url then they should not be getting the ASPXAuth cookie as this cookie is set as "HttpOnly" cookie by SharePoint/ASP.NET Form Authentication Handler? After monitoring the office appliations, I noticed that I office applications directly access the local cookie folder to read the cookies files.

My only guess is they are bypassing any standard windows call s and reading the temporary internet folder for cookies and parsing the cookies using undocumented features:) . Agreed, its a good feature to support the form authentication with office applications but directly accessing cookies is not something I expected specially after all the preaching they did on the securities

Your thoughts please?

Friday, July 20, 2007

ChangePassword page for FBA(Form based Authentication) for SharePoint 2007

One of the nice features of SharePoint is its pluggable authentication. Its actually a ASP.NET 2.0 feature. Since SharePoint 2007 is an ASP.NET application, SharePoint inherits it for free.

SharePoint provides an out-of-the-box login.aspx page , located in 12 hives /layouts folder, which is automatically enabled when you turn on FBA on any of the Zone. There are plenty of postings on the web on how to get your forms authentication working in WSS and MOSS

What I didn't find is change password . Once you enable the form authentication, how a user can change the password? There is a ASP.NET control but nothing out-of-the-box in SharePoint, to support this

So I decided to write a custom ASPX page to handle changepassword and provision it via "Feature" . It is very simple

Here is what the final output look like. You can download the entire sample from here.
Change Password Menu Item in Welcome menu (PersonalActions)

Change Password aspx page





Here is what I did
1) Created a simple aspx page and inherited "application.master" master page. Application.Master is located in /layouts folder . You can use any of the master pages from the /layouts folder or create a custom one.
2) Drop asp:changepassword control in the content area
<asp:changepassword id="ChangePassword1" newpasswordregularexpressionerrormessage="Error: Your password must be at least 7 characters long, and contain at least one number and one special character." newpasswordregularexpression=""></asp:changepassword>
3) Copy this page to 12 hives /layouts folder
4) Create a <CustomAction> Feature set the feature URL to /_layouts/changepassword.aspx page
<customaction id="ChangePasswordMenuId" title="Change Password" description="Change Password control" sequence="2000" location="Microsoft.SharePoint.StandardMenu" groupid="PersonalActions" > <UrlAction Url="~site/_layouts/changepassword.aspx"/>

5) Install the feature using STSADM.exe


And there you go!! You have the changepassword page with very little effort.

May be Microsoft can include this as a out of the box feature in the next version of SharePoint :)