Setting SMSC number on an Android phone

To set the SMS center number on a Samsung Galaxy SII phone do the following:

Open the dialer and enter *#*#4636#*#*. You will be greeted with a nice phone settings menu, one of those settings is named SMSC and is the SMS center number in PDU format. The format is described here along with a nice online converter, but the part we are interested in is the beginning.

For the Swedish provider Telenor the number should be 07916407080007F8 as the phone number to the sms center is +46708000708.

  • the 07 here is the length of information in number of octets.
  • the 91 signifies “international format”, basically a +.
  • The rest is the phone number, in this case 6407080007F8 as the phone number to the sms center is +46708000708, in decimal semi-octets. Because the total number of digits in the phone number is odd an F is added.

I’ve color-coded the number to make it easier to understand the whole decimal semi-octets stuff. If I did help you – leave a comment. 😉

More information on the PDU format is available here.

Fixing “Value does not fall within the expected range” error in MOSS page settings

I wrote this script to correct the error I got from MOSS when trying to edit page settings. Our site uses an internal url (wwwint.mysite.com) and an external one (www.mysite.com). The page layout seemed to have been reset to use the internal url instead of the external one, which generated the errors.

I first tried to fix the error using the gl-fixpublishingpagespagelayouturl command from Gary Lapointe’s stsadm commands, but that didn’t work, so I wrote my own custom script.

I’m posting the script here as a reference.

[ArgumentException: Value does not fall within the expected range.]
   Microsoft.SharePoint.Library.SPRequestInternalClass.GetFileAndMetaInfo(String bstrUrl, Byte bPageView, Byte bPageMode, Byte bGetBuildDependencySet, String bstrCurrentFolderUrl, Boolean& pbCanCustomizePages, Boolean& pbCanPersonalizeWebParts, Boolean& pbCanAddDeleteWebParts, Boolean& pbGhostedDocument, Boolean& pbDefaultToPersonal, String& pbstrSiteRoot, Guid& pgSiteId, UInt32& pdwVersion, String& pbstrTimeLastModified, String& pbstrContent, Byte& pVerGhostedSetupPath, UInt32& pdwPartCount, Object& pvarMetaData, Object& pvarMultipleMeetingDoclibRootFolders, String& pbstrRedirectUrl, Boolean& pbObjectIsList, Guid& pgListId, UInt32& pdwItemId, Int64& pllListFlags, Boolean& pbAccessDenied, Guid& pgDocId, Byte& piLevel, UInt64& ppermMask, Object& pvarBuildDependencySet, UInt32& pdwNumBuildDependencies, Object& pvarBuildDependencies, String& pbstrFolderUrl, String& pbstrContentTypeOrder) +0
   Microsoft.SharePoint.Library.SPRequest.GetFileAndMetaInfo(String bstrUrl, Byte bPageView, Byte bPageMode, Byte bGetBuildDependencySet, String bstrCurrentFolderUrl, Boolean& pbCanCustomizePages, Boolean& pbCanPersonalizeWebParts, Boolean& pbCanAddDeleteWebParts, Boolean& pbGhostedDocument, Boolean& pbDefaultToPersonal, String& pbstrSiteRoot, Guid& pgSiteId, UInt32& pdwVersion, String& pbstrTimeLastModified, String& pbstrContent, Byte& pVerGhostedSetupPath, UInt32& pdwPartCount, Object& pvarMetaData, Object& pvarMultipleMeetingDoclibRootFolders, String& pbstrRedirectUrl, Boolean& pbObjectIsList, Guid& pgListId, UInt32& pdwItemId, Int64& pllListFlags, Boolean& pbAccessDenied, Guid& pgDocId, Byte& piLevel, UInt64& ppermMask, Object& pvarBuildDependencySet, UInt32& pdwNumBuildDependencies, Object& pvarBuildDependencies, String& pbstrFolderUrl, String& pbstrContentTypeOrder) +215
   Microsoft.SharePoint.SPWeb.GetWebPartPageContent(Uri pageUrl, PageView requestedView, HttpContext context, Boolean forRender, Boolean includeHidden, Boolean mainFileRequest, Boolean fetchDependencyInformation, Boolean& ghostedPage, Byte& verGhostedPage, String& siteRoot, Guid& siteId, Int64& bytes, Guid& docId, UInt32& docVersion, String& timeLastModified, Byte& level, Object& buildDependencySetData, UInt32& dependencyCount, Object& buildDependencies, SPWebPartCollectionInitialState& initialState, Object& oMultipleMeetingDoclibRootFolders, String& redirectUrl, Boolean& ObjectIsList, Guid& listId) +1533
   Microsoft.SharePoint.ApplicationRuntime.SPRequestModuleData.FetchWebPartPageInformationForInit(HttpContext context, SPWeb spweb, Boolean mainFileRequest, String path, Boolean impersonate, Boolean& fGhostedPage, Byte& verGhostedPage, Guid& docId, UInt32& docVersion, String& timeLastModified, SPFileLevel& spLevel, String& masterPageUrl, String& customMasterPageUrl, String& webUrl, String& siteUrl, Guid& siteId, Object& buildDependencySetData, SPWebPartCollectionInitialState& initialState, String& siteRoot, String& redirectUrl, Object& oMultipleMeetingDoclibRootFolders, Boolean& objectIsList, Guid& listId, Int64& bytes) +691
   Microsoft.SharePoint.ApplicationRuntime.SPRequestModuleData.FetchWebPartPageInformation(HttpContext context, String path, Boolean impersonate, Boolean& fGhostedPage, Byte& verGhostedPage, Guid& docId, UInt32& docVersion, String& timeLastModified, SPFileLevel& level, String& masterpageUrl, String& customMasterPageUrl, String& webUrl, String& siteUrl, Guid& siteId, Object& buildDependencySetData) +132
   Microsoft.SharePoint.ApplicationRuntime.SPRequestModuleData.GetWebPartPageData(HttpContext context, String path, Boolean throwIfFileNotFound) +773
   Microsoft.SharePoint.ApplicationRuntime.SPVirtualFile.GetFile(String virtualPath, Boolean fetchContent) +78
   Microsoft.SharePoint.ApplicationRuntime.SPVirtualFile.GetFile(String virtualPath) +30
   Microsoft.SharePoint.ApplicationRuntime.SPVirtualPathProvider.GetFile(String virtualPath) +171
   System.Web.Hosting.VirtualPathProvider.GetFile(String virtualPath) +18
   System.Web.Hosting.VirtualPathProvider.GetFileWithCheck(String virtualPath) +11
   System.Web.FormatterWithFileInfo.GetSourceFileLines(String fileName, Encoding encoding, String sourceCode, Int32 lineNumber) +229
   System.Web.DynamicCompileErrorFormatter.get_MiscSectionContent() +926
   System.Web.ErrorFormatter.GetHtmlErrorMessage(Boolean dontShowSensitiveInfo) +837
   System.Web.HttpResponse.WriteErrorMessage(Exception e, Boolean dontShowSensitiveErrors) +820
   System.Web.HttpResponse.ReportRuntimeError(Exception e, Boolean canThrow, Boolean localExecute) +560
   System.Web.HttpRuntime.FinishRequest(HttpWorkerRequest wr, HttpContext context, Exception e) +333
# Updates page layout (wwwint -> www)

[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint.Publishing”)

$site = new-Object Microsoft.SharePoint.SPSite("http://www.mysite.com/myweb")
$web = $site.OpenWeb("subweb")
$pweb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$global:page = $pweb.GetPublishingPages()["Pages/mypage.aspx"]
$layout = $global:page.ListItem[[Microsoft.SharePoint.Publishing.FieldId]::PageLayout]
$newlayout = $layout.replace("wwwint", "www")

$global:page.ListItem[[Microsoft.SharePoint.Publishing.FieldId]::PageLayout] = $newlayout
$global:page.ListItem.SystemUpdate()

Avoiding X.509 chain policy caching when using WCF with certificate security

A while ago my customer came to me with an issue that was a bit tricky to find a solution to.

Their system uses a Windows forms client and a WCF service running on IIS7 on a Windows 2008 R2 server. The users are provided with personal certificates stored on smart cards. Those certificates are then used to authenticate the users with the WCF service using their AD accounts.

The issue my customer was facing was:
1. New employees could not log on to the system until the application pool of the web site running the WCF service was recycled.
2. Employees who got their certificates revokeed COULD log on to the system the application pool of the web site running the WCF service was recycled.

Obviously a (totally unwanted) certificate cache of some sort was causing this behavior, so after digging around a bit I found out that System.IdentityModel was caching the X.509 chain policy in memory.

The relevant web.config settings for the WCF service looked like this:

<clientCertificate>
	<authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="ChainTrust" revocationMode="Online"/>
</clientCertificate>

To solve this issue I decided to implement a custom X.509 validator that builds a X509Chain manually to prevent the policy from being cached.

I changed the above web.config lines to

<clientCertificate>
	<authentication mapClientCertificateToWindowsAccount="true" certificateValidationMode="Custom" customCertificateValidatorType="My.IdentityModel.MyX509Validator, My.IdentityModel" />
</clientCertificate>

and implemented the custom validator like this:

using System;
using System.IO;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace My.IdentityModel
{
    /// <summary>
    /// Custom x509 certificate validator
    /// Richard Ginzburg - richard@ginzburgconsulting.com
    /// </summary>
    public class MyX509Validator : X509CertificateValidator
    {
        public override void Validate(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate", "Certificate validation failed, no certificate provided");
            }

            X509ChainPolicy myChainPolicy = new X509ChainPolicy
                                                {
                                                    RevocationMode = X509RevocationMode.Online,
                                                    RevocationFlag = X509RevocationFlag.EntireChain,
                                                    VerificationFlags = X509VerificationFlags.NoFlag,
                                                    UrlRetrievalTimeout = new TimeSpan(0, 0, 10),
                                                    VerificationTime = DateTime.Now
                                                };
            X509Chain chain = new X509Chain(true) {ChainPolicy = myChainPolicy};

            try
            {
                bool ok = chain.Build(certificate);
                if(!ok)
                {
                    foreach (var status in chain.ChainStatus)
                    {
                        Logging.Log("MyX509Validator: Validation failed - " + status.StatusInformation);
                    }
                    throw new SecurityTokenValidationException("Certificate validation failed when building chain");
                }
            }
            catch (CryptographicException e)
            {
                throw new SecurityTokenValidationException("Certificate validation failed when building chain, " + e);
            }
        }
    }
}

This resolved the issue, now the changes in certificate validity take effect immediately.

Some documentation on certificate validity checking can be found here: http://technet.microsoft.com/en-us/library/bb457027.aspx .

Connecting to Mac OSX Lion with Screen Sharing (VNC)

Today I was having issues with connecting to my Mac running Lion from my Windows 7 laptop. The client let me enter my VNC password and then presented me with the Lion login screen where I couldn’t enter the user password.

After looking around a bit I finally pinpointed the problem to be in the choice of encoding in my UltraVNC client. The setting that finally worked for me is “Tight” but if that doesn’t work for you it might help to just try a couple of different ones!

Silencing the “battery charging completed” sound on a Samsung Galaxy SII

The "charging completed" notification sound can be pretty annoying, especially when it comes on at 3am. Here is a solution (requires rooted device):

  1. Download silent.ogg
  2. Rename it to TW_Battery_caution.ogg
  3. Copy the file to your phone
  4. Move it to /system/media/audio/ui overwriting the existing file. You can use Root Explorer for moving, and don’t forget to back up the original file!

Field not found: CatalogResourceMajorVersion from Commerce Server 2007

So I was trying to troubleshoot this Biztalk 2006 R2 orchestration that includes importing some data into a Commerce Server 2007 instance. CS doesn’t really want to play ball, so I decide to upgrade it to the latest service pack as that’s supposed to resolve some of the issues. Download SP2, install, migrate, restart IIS… BOOM! Exception:
MissingFieldException: Field not found: 'Microsoft.CommerceServer.Catalog.Internal.Constants.CatalogResourceMajorVersion'.]
Microsoft.CommerceServer.Catalog.CatalogContext.InternalCreate(CatalogSiteAgent catalogSiteAgent, DebugContext debugContext, CacheConfiguration cacheConfiguration) +708
Microsoft.CommerceServer.Runtime.Catalog.CommerceCatalogModule.CreateCatalogContext() +293
Microsoft.CommerceServer.Runtime.Catalog.CommerceCatalogModule.get_CatalogContext() +138
Microsoft.CommerceServer.Runtime.Catalog.CommerceCatalogModule.OnBeginRequest(Object sender, EventArgs e) +24
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +171

Google is, for once, silent… So I check the GAC and compare the version Microsoft.CommerceServer.Catalog.dll to the other CS dlls – bingo, the version of the dll is 6.0.3724.0. A quick search leads you to this MSDN blog post which tells you which version corresponds to which SP…

Apparently the dll failed to register during the sp2 install which led to the weirdness described above.

As I couldn’t find the right dll anywhere and was not able to reinstall sp2 I had to install sp1 and THEN sp2. This finally took care of the problem.

NULL values in SOAP requests

Question: how to pass a NULL value in a SOAP envelope?
Answer: Use the xsi:nil=”true” attribute on the element, and don’t forget the xsi namespace in the envelope.

Example SOAP request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Header/>
   <soapenv:Body>
      <TestService>
         <request>
            <PassNullHere xsi:nil="true" />
         </request>
      </TestService>
   </soapenv:Body>
</soapenv:Envelope>

Listing subcategories for a category in Commerce Server 2007 using a SQL query

As promised, here is the follow-up to the last post. This query gets us the names of all subcategories of a particular category in Commerce Server 2007.

DECLARE @categoryOid AS INT
SET @categoryOid = 937 ;

WITH    Cats2 ( oid, child_oid, hierarchy_level )
          AS ( SELECT   oid ,
                        child_oid ,
                        1 AS hierarchy_level
               FROM     dbo.ConsumerShop_CatalogHierarchy
               WHERE    oid = @categoryOid
                        AND CatalogName = 'ConsumerStaging'
               UNION ALL
               SELECT   h.oid ,
                        h.child_oid ,
                        c.hierarchy_level + 1 AS hierarchy_level
               FROM     dbo.ConsumerShop_CatalogHierarchy h
                        JOIN Cats2 c ON h.oid = c.child_oid
                                        AND h.CatalogName = 'ConsumerStaging'
             )
    SELECT  CategoryName
    FROM    dbo.ConsumerShop_CatalogProducts
    WHERE   oid IN ( SELECT DISTINCT ( oid ) 
					 FROM   Cats2 )

Listing categories for a product in Commerce Server 2007 using a SQL query

Commerce Server API is not exactly known for being lightning-fast, so sometimes you want to skip it altogether and just use plain old SQL to get the data.

This time I needed to find all categories (at a particular level) that a product belongs to. This was solved by the script below, which is using a recursive CTE to walk upwards through the tree.

Just set the @productId and @hierarchyLevel below and voilá!

DECLARE @hierarchyLevel INT
DECLARE @productId VARCHAR(10)
SET @hierarchyLevel = 3
SET @productId = '25853' ;

WITH Cats (oid, child_oid, hierarchy_level) AS
	(
		SELECT h.oid, h.child_oid, 1 AS hierarchy_level
		FROM dbo.ConsumerShop_CatalogHierarchy h 
		JOIN dbo.ConsumerShop_CatalogProducts p ON h.child_oid = p.oid
		WHERE p.ProductID = @productId
		AND h.CatalogName = 'ConsumerStaging'

		UNION ALL 

		SELECT h.oid, h.child_oid, c.hierarchy_level + 1 AS hierarchy_level
		FROM dbo.ConsumerShop_CatalogHierarchy h
		JOIN Cats c ON c.oid = h.child_oid
		WHERE h.CatalogName = 'ConsumerStaging'
	)
    SELECT  CategoryName
    FROM    Cats
            JOIN dbo.ConsumerShop_CatalogProducts p ON Cats.oid = p.oid
    WHERE   hierarchy_level = @hierarchyLevel
            AND BaseCatalogName = 'ConsumerStaging'

In my next post I will explain how to accomplish the opposite, i.e. find all subcategories of a category.

List does not exits in Sharepoint 2007 when accessing cache settings

When trying to access the cache settings in Sharepoint 2007 (Site Collection Administration section, Site collection output cache link).

The error I got was:

List does not exist
The page you selected contains a list that does not exist. It may have been deleted by another user.
at Microsoft.SharePoint.Library.SPRequestInternalClass.GetListsWithCallback(String bstrUrl, Guid foreignWebId, String bstrListInternalName, Int32 dwBaseType, Int32 dwBaseTypeAlt, Int32 dwServerTemplate, UInt32 dwGetListFlags, UInt32 dwListFilterFlags, Boolean bPrefetchMetaData, Boolean bSecurityTrimmed, Boolean bGetSecurityData, ISP2DSafeArrayWriter p2DWriter, Int32&amp; plRecycleBinCount) at Microsoft.SharePoint.Library.SPRequest.GetListsWithCallback(String bstrUrl, Guid foreignWebId, String bstrListInternalName, Int32 dwBaseType, Int32 dwBaseTypeAlt, Int32 dwServerTemplate, UInt32 dwGetListFlags, UInt32 dwListFilterFlags, Boolean bPrefetchMetaData, Boolean bSecurityTrimmed, Boolean bGetSecurityData, ISP2DSafeArrayWriter p2DWriter, Int32&amp; plRecycleBinCount

After a bit of searching and asking around I found out that the culpit is the Office Sharepoint Server Publishing Infrastructure feature.

Apparently caching control breaks when a site is upgraded and this feature has to be deactivated and then reactivated to resolve the issue. The feature can be found in site collection features section.