Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

URL sharing across a network with ASP.NET

0.00/5 (No votes)
3 Sep 2003 2  
This ASP.NET application allows the sharing of Internet Explorer Favorites URLs over an intranet or the Internet.

URL Explorer picture

Introduction

URL Explorer is an ASP.NET application which displays the content of a generated XML file, representing the structure of your Favorites folder with the help of an XSLT stylesheet. URL Explorer allows the sharing of Internet Explorer shortcuts over an intranet or the Internet.

With URL Explorer you can:

  • Browse easily through the folders of your Internet Explorer Favorites
  • Access alphabetically sorted list of your Internet Explorer Favorites
  • Share your URLs across a network

What URL Explorer performs:

  • Recursively parse through the file system
  • Reading of an INI file with .NET
  • Generating an XSL transformation to an XML file
  • Mixing of ASP.NET, JavaScript and CSS

Background

Sharing files and various documents has been at the origin of the networking technology and of the Internet as a whole. While it is quite common to share files over a network, it is curious to realize that URLs sharing is not common at all.

It is also quite weird to consider the non user-friendly internet shortcuts management of Microsoft Internet Explorer, even in its last version and service pack!! Just launch your Internet Explorer, click the Favorites menu, and have a look at the disaster: non alphabetically sorted URLs, folders and shortcuts, mixed altogether, making it difficult to find out the one you are looking for.

We could have expected as a result of the Microsoft/Netscape browser war, that we would have won the benefice of a better tool, but it is apparently not the case. Microsoft won not by offering the best product, but by slowly killing its opponent, as usual could we say...

Nevertheless, we don�t need more to develop an ASP.NET application which could help us through these drawbacks. If software were perfect, we wouldn�t have a job anymore would we?

How it works

The ASP.NET application is a set of 3 pages put together with a frame HTML page.

  • Bookmarks.htm is the HTML page serving as container for the different frames.
  • BookmarksTop.aspx is the banner page of the application. As it performs the generation of the XML file containing the Internet Explorer shortcuts, it is a Web form.
  • Bookmarks.aspx displays the folder view tree. It is also a Web form because the HTML output is generated with an XSLT transform stylesheet.
  • Url.htm is the HTML page displaying the list of the URLs contained in the different folders. No need of a Web form since no peculiar operation is performed for the display.

Basically, the URL view tree displayed when the ASP.NET application is launched, is a result of the XSL transform of the Bookmarks.xml file in the application directory. Of course it does not reflect the content of your personal Favorites directory. To do so, type the path of your Favorites folder in the textbox of the banner, then click the Refresh button.

To customize URL Explorer, change the value of the cFavoritesPath variable in the Bookmarks.aspx.cs file. Compile the application again and run it. Then the value of your personal path will appear in the textbox at the launch of the program.

Security concerns

Considering our scenario of sharing URLs across a network, some security concerns are coming out right, before we start coding. The first matter of concern is the access to the Favorites protected folder in the Document and Settings folder. This is the place where Windows stores all information about a user. Open the Windows Explorer, go to the location drive of Windows, expand the � Documents and Settings � folder and right-click on the user folder (here JMC), the following Dialog box should pop up on your screen.

Favorites-Security picture

Figure 1: The Security tab of the Favorites folder after granting all rights to ASP.NET.

In the list of trusted users, you can see the Administrators and SYSTEM groups as well as my personal account on the computer: JMC since I am the owner of the folder. The problem here is that ASP.NET cannot access the folder and even not list its content, which doesn�t allow us to do much with our application.

To grant access to the user�s folder with ASP.NET, follow these steps:

  • Right-click on the user�s folder in � Documents and Settings � as described above
  • Click on the Add� button
  • The Select Users or Groups dialog box pops up
  • Select ASPNET user in the list and click the Add� button
  • The dialog should appear as follows, with a different name for your computer of course:

    Select Users or Groups picture

    Figure 2:The Select Users or Group dialog

  • Click OK to close the dialog

The security tab of your folder should now appear as Figure 1 above.

For the purpose of our application we do not need the full Control over the folder, which would mean the right to change the access rights, to delete and to modify the folders.

Of course, when the application is to be used over an intranet, ask yourself a few questions about security: should the ASP.NET application be able to access the whole content of your Documents and Settings folder, including the sub-folders where private information might be saved, in the My Documents folder for instance ? While not important when the application is locally run, the question is an important one when run on a server over a network.

The solution here lies in the creation of a dedicated shared folder on the server for this purpose alone. The Internet Explorer shortcuts and the folder structure are to be copied to this special folder and the processing of reading the folder�s content, generating the XML file and displaying its URLs would take place there.

Parsing through the files and folders

Parsing through the file system is a recursive procedure as shown on figure 3. Folders may contain files as well as other folders, and so on, as we all know.

Just invoke once for all the GetFolders() method with the entry point that we need to read and that's all. In my case the entry point of my favorites Internet shortcuts is E:\Documents and Settings\JMC\Favorites where JMC is the name of the logged user. In the method, every time a folder or a file is met, an element is added to the XML file with its name along, as an attribute.

Files and Folders UML diagram.gif

Figure 3: Parsing files and folders - Sequence Diagram

private void GetFolders(XmlNode parentNode, string parentPath)
{
    string [] subdirectoryEntries = Directory.GetDirectories(parentPath);
    foreach(string subdirectory in subdirectoryEntries)
    {
        int index = subdirectory.LastIndexOf(@"\");
        string cRootFolderName = subdirectory.Substring(
                                        index+1,
                                        subdirectory.Length-index-1);
        string cRelativePath = 
            subdirectory.Substring(cFavoritesPath.Length);
        XmlElement elem = _doc.CreateElement("folder");
        XmlNode newChild = parentNode.AppendChild(elem);
        newElement(newChild, cRootFolderName, cRelativePath);
        GetFiles(newChild, subdirectory);
        GetFolders(newChild, subdirectory);
    }
}

private void GetFiles(XmlNode parentNode, string parentPath)
{
    string [] fileEntries = Directory.GetFiles(parentPath);
    foreach(string fileName in fileEntries)
    {
        //If the file is a web shortcut, get the URL                

        
        //Check the extension of the file

        string cURL = "";
        int DotIndex = fileName.LastIndexOf(@".");
        string cExtension = fileName.Substring(DotIndex+1,
                                 fileName.Length-DotIndex-1);
        if (cExtension.CompareTo("url") == 0)
        {    
            StringBuilder buffer = new StringBuilder(256);
            if (buffer != null) 
            {
                int bufLen = GetPrivateProfileString(
                                     "InternetShortcut",
                                     "URL", 
                                     "", 
                                     buffer, 
                                     buffer.Capacity, 
                                     fileName);
                cURL = buffer.ToString();

                //Get the name to be displayed: 

                //remove the full path & the '.url' extension

                int SlashIndex = fileName.LastIndexOf(@"\");
                string cDisplayName = 
                         fileName.Substring(SlashIndex+1,
                         fileName.Length-SlashIndex-5);
                XmlElement elem = _doc.CreateElement("file");
                XmlNode newChild = parentNode.AppendChild(elem);
                newElement(newChild, cDisplayName, cURL);                
            }
        }
    }
}

//Create a new element in the XML file

private void newElement(XmlNode parentNode, 
        string Attributename, string Attributepath)
{        
    XmlNode attrName = _doc.CreateNode(XmlNodeType.Attribute, 
                                                    "name", "");
    attrName.Value = Attributename;
    parentNode.Attributes.SetNamedItem(attrName);

    XmlNode attrPath = _doc.CreateNode(XmlNodeType.Attribute, 
                                                   "path", "");
    attrPath.Value = Attributepath;
    parentNode.Attributes.SetNamedItem(attrPath);
}

Read an .INI file with .NET

As shown below, an Internet Explorer shortcut is basically an INI file containing several "Profiles". What we need to read is the content of the URL entry in the [InternetShortcut] profile to get the URL that we want.

[DEFAULT]
BASEURL=http://www.jaeggi.ch/index_home.php
[InternetShortcut]
URL=http://www.jaeggi.ch/index_home.php
Modified=20ECDB547D5DC301D9
IconFile=http://www.jaeggi.ch/favicon.ico
IconIndex=1

As INI files are not used anymore in the .NET framework, there is no available method to easily get its content... This is the point where you should take advantage of our experience with the "old" Windows programming techniques. In those times, there was a function called GetPrivateProfileString() from a Windows DLL that would read the content of an INI file, given a profile and an entry name. Just declare it in .NET as shown below and you can use it as a standard .NET method.

//This "old" Windows function allows us to 

//read the content of the .url files

[DllImport("KERNEL32.DLL",EntryPoint="GetPrivateProfileString")]
protected internal static extern int 
    GetPrivateProfileString(string lpAppName, 
    string lpKeyName, string lpDefault, 
    StringBuilder lpReturnedString, int nSize, 
    string lpFileName);

Performing XSL transform

Once we have the XML file representing our Internet shorcuts structure, we need to represent it with our browser. A very convenient way is to use XSL transformation stylesheet capabilities. It is very powerful and allows us to make changes even after the ASP.NET application is compiled, since it is interpreted client side by the browser.

The XSL stylesheet file is shown below:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/">
   <html>
        <head>
        <link rel="stylesheet" type="text/css" href="bookmarks.css"/>
        <script type="text/javascript" src="folder.js"></script>
        <title>R�pertoire=<xsl:value-of select="folder/@path"/></title>
        </head>
   <body>

<table cellspacing="0" cellpadding="0">    
    <tr>
        <td>
<xsl:apply-templates select="folder"><xsl:sort 
          select="@name" /></xsl:apply-templates>
        </td>
    </tr>
</table>
</body>
</html> 
</xsl:template>

<xsl:template match="folder">
<DIV CLASS="wrapping">
<DIV CLASS="folder" onclick="Toggle(this)" title="Click to unfold">
    <span><img src="closed.gif"/></span>
    <span style="display:none"><img 
         src="open.gif"/>
    </span><xsl:value-of select="@name"/>
</DIV>
<DIV CLASS="folder" STYLE="display:none">
  <xsl:apply-templates select="folder">
  <xsl:sort select="@name" />
  </xsl:apply-templates>
</DIV>
<table border="1" topmargin="0" leftmargin="0" rightmargin="0" 
  cellspacing="1" cellpadding="4" width="100%" STYLE="display:none">
<xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute>
<xsl:attribute name="path"><xsl:value-of select="@path"/></xsl:attribute>
<xsl:apply-templates select="file[position() mod 3 = 1]">
  <xsl:sort select="@name" />
</xsl:apply-templates>  
</table>
</DIV>                           
</xsl:template>
  
<xsl:template match="file">
<tr>
<xsl:apply-templates select="." mode="suite"/>
<xsl:apply-templates select="following-sibling::file[position()=1]" 
                                                        mode="suite"/>
<xsl:apply-templates select="following-sibling::file[position()=2]" 
                                                        mode="suite"/>
</tr>    
</xsl:template>

<xsl:template match="file" mode="suite">
<td>
<a target="_blank"><xsl:attribute name="href"><xsl:value-of select="@path"/>
</xsl:attribute>
<xsl:value-of select="@name"/></a>
</td>
</xsl:template>

</xsl:stylesheet>

Extensions

The source code in the project allows the updating of the underlying XML file for demonstration purpose. In a real life project, it would certainly have a lot more sense not to allow your users to change the content of the file, as the processing time may cost a few seconds, every time the URL tree is refreshed.

As suggested above, for security reasons, a good practice would be to copy the Internet shortcuts and folders to a shared folder.

The total amount of transferred data when the page is invoked can be huge and may take a while to load. In that case, an extension to the program would be to load only the root folders, and search in the XML file, the folders they are having, once clicked.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here