private BlogAccountFromRsdServiceDescription(RsdServiceDescription rsdServiceDescription) { // look for supported apis from highest fidelity to lowest RsdApi rsdApi = rsdServiceDescription.ScanForApi("WordPress"); if (rsdApi == null) rsdApi = rsdServiceDescription.ScanForApi("MovableType"); if (rsdApi == null) rsdApi = rsdServiceDescription.ScanForApi("MetaWeblog"); if (rsdApi != null) { Init(rsdServiceDescription.EngineName, rsdApi.Name, rsdApi.ApiLink, rsdApi.BlogId); return; } else { // couldn't find a supported api type so we fall through to here throw new NoSupportedRsdClientTypeException(); } }
/// <summary> /// Read the definition of a blog service from the passed RSD XML /// </summary> /// <param name="rsdStream"></param> /// <returns></returns> private static RsdServiceDescription ReadFromRsdStream(Stream rsdStream, string url) { // initialize a blog service to return RsdServiceDescription rsdServiceDescription = new RsdServiceDescription(); rsdServiceDescription.SourceUrl = url; ArrayList blogApis = new ArrayList(); try { // liberally parse the RSD xml XmlReader reader = new XmlTextReader( SkipLeadingWhitespace(new StreamReader(rsdStream, new UTF8Encoding(false, false)))); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { // windows-live writer extensions to rsd if (UrlHelper.UrlsAreEqual(reader.NamespaceURI, WINDOWS_LIVE_WRITER_NAMESPACE)) { /* switch ( reader.LocalName.ToLower() ) { case "manifestlink": rsdServiceDescription.WriterManifestUrl = reader.ReadString().Trim() ; break; } */ } // standard rsd elements else { switch (reader.LocalName.ToUpperInvariant()) { case "ENGINENAME": rsdServiceDescription.EngineName = reader.ReadString().Trim(); break; case "ENGINELINK": rsdServiceDescription.EngineLink = ToAbsoluteUrl(url, reader.ReadString().Trim()); break; case "HOMEPAGELINK": rsdServiceDescription.HomepageLink = ToAbsoluteUrl(url, reader.ReadString().Trim()); break; case "API": RsdApi api = new RsdApi(); for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); switch (reader.LocalName.ToUpperInvariant()) { case "NAME": api.Name = NormalizeApiName(reader.Value); break; case "PREFERRED": api.Preferred = "true" == reader.Value.Trim(); break; case "APILINK": case "RPCLINK": // radio-userland uses rpcLink api.ApiLink = ToAbsoluteUrl(url, reader.Value.Trim()); break; case "BLOGID": api.BlogId = reader.Value.Trim(); break; } } blogApis.Add(api); break; case "SETTING": if (blogApis.Count > 0) { RsdApi lastRsdApi = (RsdApi)blogApis[blogApis.Count - 1]; string name = reader.GetAttribute("name"); if (name != null) { string value = reader.ReadString().Trim(); lastRsdApi.Settings.Add(name, value); } } break; } } } } } catch (Exception ex) { Trace.Fail("Exception attempting to read RSD file: " + ex.ToString()); // don't re-propagate exceptions here becaus we found that TypePad's // RSD file was returning bogus HTTP crap at the end of the response // and the XML parser cholking on this caused us to fail autodetection } // if we got at least one API then return the service description if (blogApis.Count > 0) { rsdServiceDescription.Apis = (RsdApi[])blogApis.ToArray(typeof(RsdApi)); return rsdServiceDescription; } else { return null; } }
public static BlogAccount Create(RsdServiceDescription rsdServiceDescription) { try { return new BlogAccountFromRsdServiceDescription(rsdServiceDescription); } catch (NoSupportedRsdClientTypeException) { return null; } }
private bool AttemptRsdBasedDetection(IProgressHost progressHost, RsdServiceDescription rsdServiceDescription) { // always return alse for null description if (rsdServiceDescription == null) return false; string providerId = String.Empty; BlogAccount blogAccount = null; // check for a match on rsd engine link foreach (IBlogProvider provider in BlogProviderManager.Providers) { blogAccount = provider.DetectAccountFromRsdHomepageLink(rsdServiceDescription); if (blogAccount != null) { providerId = provider.Id; break; } } // if none found on engine link, match on engine name if (blogAccount == null) { foreach (IBlogProvider provider in BlogProviderManager.Providers) { blogAccount = provider.DetectAccountFromRsdEngineName(rsdServiceDescription); if (blogAccount != null) { providerId = provider.Id; break; } } } // No provider associated with the RSD file, try to gin one up (will only // work if the RSD file contains an API for one of our supported client types) if (blogAccount == null) { // try to create one from RSD blogAccount = BlogAccountFromRsdServiceDescription.Create(rsdServiceDescription); } // if we have an rsd-detected weblog if (blogAccount != null) { // confirm that the credentials are OK UpdateProgress(progressHost, 65, Res.Get(StringId.ProgressVerifyingInterface)); BlogAccountDetector blogAccountDetector = new BlogAccountDetector( blogAccount.ClientType, blogAccount.PostApiUrl, _credentials); if (blogAccountDetector.ValidateService()) { // copy basic account info _providerId = providerId; _serviceName = blogAccount.ServiceName; _clientType = blogAccount.ClientType; _hostBlogId = blogAccount.BlogId; _postApiUrl = blogAccount.PostApiUrl; // see if we can improve on the blog name guess we already // have from the <title> element of the homepage BlogInfo blogInfo = blogAccountDetector.DetectAccount(_homepageUrl, _hostBlogId); if (blogInfo != null) _blogName = blogInfo.Name; } else { // report user-authorization error ReportErrorAndFail(blogAccountDetector.ErrorMessageType, blogAccountDetector.ErrorMessageParams); } // success! return true; } else { // couldn't do it return false; } }
private BlogAccount ScanForSupportedRsdApi(RsdServiceDescription rsdServiceDescription) { // initialize client type mappings (including mapping "implied" from ClientType itself ArrayList rsdClientTypeMappings = new ArrayList(_rsdClientTypeMappings); rsdClientTypeMappings.Add(new RsdClientTypeMapping(ClientType, ClientType)); // scan for a match foreach (RsdClientTypeMapping mapping in rsdClientTypeMappings) { RsdApi rsdApi = rsdServiceDescription.ScanForApi(mapping.RsdClientType); if (rsdApi != null) { // HACK: the internal spaces.msn-int site has a bug that causes it to return // the production API URL, so force storage.msn.com to storage.msn-int.com string postApiUrl = rsdApi.ApiLink; if (rsdServiceDescription.HomepageLink.IndexOf("msn-int", StringComparison.OrdinalIgnoreCase) != -1) postApiUrl = postApiUrl.Replace("storage.msn.com", "storage.msn-int.com"); return new BlogAccount(Name, mapping.ClientType, postApiUrl, rsdApi.BlogId); } } // no match return null; }
virtual public BlogAccount DetectAccountFromRsdEngineName(RsdServiceDescription rsdServiceDescription) { if (IsMatch(RsdEngineNameRegex, rsdServiceDescription.EngineName)) { return ScanForSupportedRsdApi(rsdServiceDescription); } else { return null; } }
virtual public BlogAccount DetectAccountFromRsdHomepageLink(RsdServiceDescription rsdServiceDescription) { if (IsMatch(RsdHomepageLinkRegex, rsdServiceDescription.HomepageLink)) { return ScanForSupportedRsdApi(rsdServiceDescription); } else { return null; } }