« November 2003 | Main | February 2004 »

January 31, 2004

Copy Constructors, MemberwiseClone, and the ICloneable Interface

After looking at the options a bit, here are some conclusions about Copy Constructors, MemberwiseClone, and the ICloneable Inerface in C#:

1.       Generally favor factory methods (like Clone and Deserialize) over copy constructors unless you’re really aiming at value semantics. They’ll be more consistent with the way serialization works and the existing patterns.

2.       It’s easy to implement a Clone method in terms of a copy constructor and impossible to do the opposite, but…

3.       Object.MemberwiseClone supports writing Clone methods and not copy constructors.

4.       Like many things in the pre-generics flavor of C#, the “object” return type of ICloneable.Clone is unfortunate, but just deal with it.

5.       Don’t overlook using serialization if you just need some kind of copy operation.

 

January 30, 2004

Getting correctly encoded HTML from Microsoft Word in a .NET implemented COM Add-in

In the context of a COM Add-in for Microsoft Word 2003, I wanted to convert selected content in a Word document to an HTML string for shipment up to a web service.

The first approach was, in C#:

                  Selection.Cut();

                  IDataObject cdo = Clipboard.GetDataObject();

                  body = (string) cdo.GetData(DataFormats.Html);

Which fails on things like the copyright symbol and smart quotes. It appears that the wrong encoding is being applied to the clipboard data on the way to creating what should be a Unicode string.

To get a bit more control, the second approach saved a temporary document as FilteredHTML and then read it back in as a string.

Looking at the content of the temporary files it appeared that they were being encoded using the windows-1252 character set. Since UTF-8 and Unicode encodings were failing, I leaped to the conclusion that the code page 1252 encoding might do the trick and voila:

                  using (FileStream fs = File.OpenRead(Path.Combine(path, filename))) {

                        byte[] bytes = new byte[fs.Length];

                        fs.Read(bytes, 0, (int)fs.Length);

                        html = Encoding.GetEncoding(1252).GetString(bytes);

                  }

 

This produces a Unicode string “html” which gets symbols such as €£¥©®™±≠≤≥αβ right.

 

Word add-in supporting posting to Dottext from Word

When I'm working, my usual mode of operation is to have a Word document open (typically Notebook.doc) in which I'll have several active entries. We rarely get to work on one thing at a time anymore, and that's reflected in my note taking.

To start a new entry, I hit a control-alt-A, and a macro inserts the start of an entry header at the end of the file. I complete the header by typing a comma separated list of categories and a short descriptive title; all in one paragraph; hit enter and start the body of the entry.

As I bounce between tasks, I'll edit the body of the corresponding entry and maybe the header as well.

Eventually the entry is done and it needs to be archived and optionally posted to a blog.

I archive each entry as an ordinary Word document in a tree of folders on my laptop. This is my primary repository since it is secure, accessible off-line and can handle rich content. The search function of Windows Explorer is also useful for finding old entries.

If the entry is suitable for posting to a blog, I add the name of the blog to the header and it gets posted at the same time.

This is the first real entry made this way, I'll be adding more information and sharing the implementation once it gets more fully baked.

January 21, 2004

Initial experiences with FlexWiki setup

I installed FlexWiki on my public web server under http://wiki.toneengel.com without a hitch.

The next step was to enable secure access to a client namespace.

I settled on Windows Integrated security because Forms isn’t really secure without SSL, Passport is too expensive, and Windows Integrated is secure and relatively easy to enable.

I’ve discovered two problems with Windows Integrated security for this application:

1.       There doesn’t seem to be any browser level support for changing passwords which means I’ll end up having to manually build some kind of password add/change user functionality which will again leave application code handling user passwords.

2.       A login dialog appears separately for each web site with Windows Integrated security enabled and access restricted. I was initially storing restricted image content on one site and referring to them from my wiki site. Created a separate folder in the wiki namespace root folder to store downloadable content so that it would inherit the same ACLs as the wiki.

Along the way to getting the wiki namespace setup and after creating a bunch of pages I discovered that I’d chosen a poor namespace naming convention which led to moving the pages from one namespace root folder to a new one. This probably should have been painless except along the way to settling on ACLs I’d left things such that all the content was inaccessible from the administrator account used to manage the web server. After taking ownership of the content and moving it and fixing a few links, everything worked great except for one thing.

I’m now noticing that when I click Edit to begin modifying an existing page FlexWiki very often seems to get confused about the presence of an existing page and displays the new blank page template and the new page creation notice. This is particularly likely if the browser’s refresh or back commands were used prior to clicking Edit. Following wiki links to the page always seems to make Edit work correctly. Very strange.

2004-01-22 09:01 Thu, The beginnings of understanding.

They key is that some operations trigger a Windows Authentication login and others don’t.

Actions that trigger login:

Requesting a ACL restricted page. (with or without the IIS Anonymous Access enabled)

Requesting a page from a site or subfolder that has Anonymous Access disabled.

Things that don’t trigger login:

                File.OpenRead, File.OpenWrite, File.Exists, new DirectoryInfo of an ACL restricted file or location.

January 20, 2004

Web Site Security, Authentication

Good MSDN overview topic: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsent7/html/vxconaspnetauthentication.asp

Use System.Threading.Thread.CurrentPrincipal to obtain and IPrincipal interface, then Idendity for an IIdentity interface, which has properties Name, IsAuthenticated, AuthenticationType.

System.Security.Principal.IIdentity i = System.Threading.Thread.CurrentPrincipal.Identity;

Trace.Write("Authentication", string.Format("Name={0} Is={1} Type={2}", i.Name, i.IsAuthenticated, i.AuthenticationType));

 

The web.config file defines which authentication modules will be activated for an ASP.NET application.

Windows is the default.(?)

Windows is secure and easy in terms of coding; a bit tricky to ensure correct behavior; and only handles IE >5.x browsers. It uses Kerberos if the server is running Active Directory, otherwise NTLM.

Passport is a commercial solution. Licensing is $10k per year per company + $1.5k per year per URL. Coding is required. Start by downloading the SDK.

Forms is the most flexible and requires the most work to make secure. SSL is required for any real security. Requires clients to trust each web site with their un-encrypted password.

Windows Authentication Details

Add the following to web.config as children of the system.web element:

<authentication mode="Windows" />

<identity impersonate="true"/>

 

I still haven’t experimentally confirmed the behavior of identity impersonation.

The authorization element can be used to add allow and deny elements. "*" means all users. "?" means the anonymous user. Both lists are supposed to allow comma separated lists of users. I haven’t determined the required syntax yet. E.g. with or without domain or machine prefix, fully qualified or not, etc.

<authorization>

    <allow users="*" />

    <deny users="?" />

</authorization>

 

You can also put a block like the following at the configuration element child level to put constraints on a specific path. If the path is omitted, the constraint is applied to the folder containing the web.config file.

<location path="consulting.aspx">

   <system.web>

       <authorization>

        <allow users="*" />

    </authorization>

   </system.web>

 </location>

 

Access control is a combination of file system ACLs, IIS security settings, and web.config authorization elements.

 

ACL

IIS Directory Security à

Authentication & Access Control

web.config

Baseline Settings
Public access

Everyone: full control

INTERACTIVE: Read & Execute (folders only)

NETWORK: Read & Execute (folders only)

SYSTEM: Read (folders only) & Execute (folders only)

Anonymous access enabled.

Integrated Windows authentication.

No authorization elements: access allowed.

<deny users="?" />: forces authentication then allows access.

Access Restricted to Group

Group: full control

Administrators: full control

SYSTEM: Read (folders only) & Execute (folders only)

Anonymous access DISABLED.

Integrated Windows authentication.

No authorization elements: access is allowed only after login by group member.

Could not simply add the Administrator account to the Group. For some reason this doesn’t work.

<allow users="*" />: BOGUS, can’t give privileges the ACL doesn’t allow.

<deny users="*" />: Denies access to everyone. (UNSURE THIS ALWAYS WORKS)

 

Microsoft Passport authentication service licensing fee

The cost for using Microsoft's Passport authentication service on a web site is roughly $10,000 per year per company plus $1,500 per year per URL.

See the Passport Review Guide .

January 19, 2004

WikiPedia.org, A free encyclopedia being written by almost everyone that wants to.

While thinking about practical applications of wikis and worrying about the portential work load arising from vandalism to a public wiki I came across www.wikipedia.org, which is a free, public encyclopedia being written by everyone that wants to.

Well almost everyone. There's actually a page here where the vandalism battle is documented.

At first glance, it looks like they've found the vandalism workload to be remarkably light.

Maybe there's hope for humanity after all.

January 16, 2004

SCC Switch Provider: C# Visual Studio project to change source control provider.

Joined the FlexWiki GotDotNet group last night for source code access which is provided through a custom source code control provider that integrates with Visual Studio.

That led to looking for an easy tool to switch SCC between GDN and Perforce. Such a tool existed on GDN but only as an exe, so I used Lutz Roeder’s Reflector to reverse engineer it into a new C# project. Download.

Remember to call the Microsoft.Win32.Registry.LocalMachine.OpenSubKey method with a second argument of true to indicate that write access is required when writing to a key.

SCC Switch Provider, GotDotNet Source Control

Joined the FlexWiki GotDotNet group last night for source code access which is provided through a custom source code control provider that integrates with Visual Studio.

That led to looking for an easy tool to switch SCC between GDN and Perforce. Such a tool existed on GDN but only as a rather anonymous exe, so I used Lutz Roeder’s Reflector to reverse engineer it into a new C# project.

Only snag was not calling the Microsoft.Win32.Registry.LocalMachine.OpenSubKey method with a second argument of true to indicate that write access was required. That led to a rat chase on security and permission settings.

January 13, 2004

Excellent source tree comparison and differencing tool: WinMerge

To speed up integrating Scott's latest Dottext changes with my own mods I went looking for an easy way to pinpoint changes in trees of source files.

WinMerge does the job well and its free. Highly recommended.

January 11, 2004

Controlling Internet Explorer caching of static content

HTTP Headers

Cache-control: post-check=60,pre-check=3600

Post-check means update the content after returning what you’ve got if necessary.

Pre-check means update the cache if necessary before returning the content.

Expires:

Time in minutes from retrieval to expiration. Stored as an expiration time with cached content.

Setting HTTP Headers

Programmatically when constructing a response.

      Response.Expires = (int) TimeSpan.FromMinutes(1.0).TotalMinutes;

In HTML. <META HTTP-EQUIV="REFRESH" CONTENT="0;URL=foo.aspx">

In IIS under page, folder, and site properties à HTTP Headers.

Behavior

With an HTTP Expires header value of one, a new page is fetched from the server if the locally cached copy is more than one minute stale.

Note that requesting a refresh in the browser always goes to the server.

Just entering the address again and pressing Go (or typing Enter) will only go to the server if Expires is set and has expired.

The IE cache behavior is the same between “.htm” and “.aspx” content.

With an Expires HTTP header, a new browser process will return a client cached page if it’s not expired.

Without an Expires HTTP header (None), a new browser always fetches a page the first time, even if it is in the cache.

Subsequently, enter will not fetch but refresh will.

In IE, ToolsàInternet Options…àSettings…àView Files… brings up a Windows Explorer view of cached content including expiration datetimes.

Cached IE content is stored here by default: C:\Documents and Settings\{profile_name}\Local Settings\Temporary Internet Files.

Good reference on use of treemaps in user interface design

Treemaps for space-constrained visualization of hierarchies

by Ben Shneiderman, December 26, 1998, updated May 21, 2003

IE5 & IE6 blockquote with border CSS bug workaround

There’s an IE5 & IE6 cascading style sheet (CSS) bug affecting the “AnotherEon001” skin.

The bug is visible if a post contains a “blockquote” element which contains a “P” element.

What you’ll see is all the text following the “div” containing the “blockquote” will be shifted to the left from where it should have been.

The trigger for the bug is the “border-left” style applied to the “blockquote”.

Alternatives to avoid the bug:

1.      Remove the “border-left” style.

2.      Add a “border-bottom” style of equal width. Make it match the background if you don’t want to see it.

3.      Eliminate the “padding” style from the “blockquote”.

4.      Somehow arrange for the text within the “blockquote” not to contain any “p” elements J

Thanks for the insight into the bug goes to this link.

Share your RSS subscriptions with the world

 For reference when it comes time J to care about this myself…

If you haven't checked it out yet, you should really take a look at

http://feeds.scripting.com/rankings

Basically it's a site that allows you to upload your OPML file and share it with others. The link here shows the top 100 feeds people subscribe to. You can also go to each person and see their OPML list. You can also see who subscribes to your feed. Sadly, it seems that only 5 people subscribe to me, which is even less than my imagined 10 readers :)   (but then, Lutz Roeder's feed only has 3 subscriptions so what do I know)

Anyway, I just discovered some very cool feeds from there but I think it's still little known. So, what do you subscribe to? (BTW: you need to manually enable sharing your subscriptions so that you will be counted as a subscriber to someone else's feeds) 

(This is not aggregated on the main site so that I only bother the people who actually subscribe to my blog)


[ISerializable]

January 08, 2004

Dottext modification to extract categories and creation date from title string

This patch to Dottext is intended to simplify importing historical posts and allows you to assign categories when posting from Outlook using NewsGator.

You can download a zip of the modified source and binaries.

Details:

·         Looks for comma separated date and categories in the title string. If they are found, they are removed from the remainder of the title.

·         Categories are matched based on their title string and are case insensitive.

·         Both the web/admin add-new-post code and the web/service code used by NewsGator have been updated.

·         The date formats recognized are: "u", "s", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss ddd", "yyyy-MM-dd HH:mm ddd", "yyyy-MM-dd ddd".

For example, to create a new posting that you actually composed last night while off-line and would like to categorize under both dotNET and Dottext, enter a NewsGator "Subject:" or admin "Post Title" as follows:

2004-01-07 23:00, dottext, dotnet, This is the actual post title about dottext and dotnet stuff

The date, categories, and commas will be stripped from the actual post title.

Sort of a Wiki approach to supplying post meta data.

Dottext version patched:

·         Dottext 0.95.2004.102 Source

Files modified/added:

·         Code\DottextWeb\Admin\UserControls\EntryEditor.ascx.cs

·         Code\DottextWeb\Services\SimpleBlogService.asmx.cs

·         Code\Dottext.Framework\Util\TitleParser.cs

Visual Studio option to open .ascx files in HTML mode by default

 The Visual Studio option to open .ascx files in HTML mode by default is under:

Tools->Options->HTML Designer->General

Fixing inaccessible object owners in a restored SQL Server database

After restoring a backup of a hosted database using SQL Server Authentication I was unable to access all the objects (tables and stored procedures).

I guessed that the problem stemmed from the “User” not appearing under Security as a “Login”. I can create an identically named Login but it appears to remain separate from the User, complaining if I attempt to give it access to the restored database.

 This MSDN article contains a stored procedure that should be able to change the object owner on all objects in a database.

Executing the stored procedure runs through all the correct objects without error, but doesn’t change anything.

Reading the fine print confirms that it only prints out the commands that should do the actual work. Copy the output and execute it.

If you execute all the statements printed, expect to see a variety of error messages: Object ‘foo’ does not exit… These appear to be caused by key, index, and trigger ownership change being effected by a prior table ownership change.

 

January 06, 2004

Hashing with Salt, SHA-1, Base64, MD5

Hashing with Salt, SHA-1, Base64, MD5