using
System;
using
System.Collections.Generic;
using
System.IO;
using
System.Net;
using
System.Security.Principal;
using
System.Text;
using
System.Text.RegularExpressions;
using
System.Collections.Specialized;
using
System.Web;
namespace PS.Utils.FPRPC{
/// <summary>
/// Client for calling Front Page Server Extensions.
/// </summary>
public
class
FrontPageRPC
{
private
readonly ICredentials credentials;
private
static
string serverExtensionsVersion;
private
const
string STR_AUTHOR_DLL_PATH = "/_vti_bin/_vti_aut/author.dll";
private
const
string STR_VTI_RPC_PATH = "/_vti_bin/shtml.dll/_vti_rpc";
private
const
string defaultServerVersion = "6.0.2.5614";
public
FrontPageRPC()
: this(CredentialCache.DefaultCredentials)
{
}
public
FrontPageRPC(ICredentials credentials)
{
this.credentials = credentials;
}
/// <summary>
/// Has WSS parse the site vs. file/folder portion of a URL.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public
WebUrl UrlToWebUrl(string uri)
{
WebUrl webUrl = new
WebUrl();
Uri aUri = new
Uri(uri);
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "url to web url:" + defaultServerVersion);
methodData.Add("url", aUri.AbsolutePath);
methodData.Add("flags", "0");
string response = SendSimpleRequest(GetVtiRPC(aUri.GetLeftPart(UriPartial.Authority)), methodData);
webUrl.SiteUrl = aUri.GetLeftPart(UriPartial.Authority) + GetReturnValue(response, "webUrl");
webUrl.FileUrl = HttpUtility.UrlDecode(GetReturnValue(response, "fileUrl"));
return webUrl;
}
public
DocumentInfo GetDocument(WebUrl webUrl, Stream outStream)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "get document:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "");
methodData.Add("document_name", webUrl.FileUrl);
methodData.Add("get_option", "none");
methodData.Add("timeout", "10");
using (Stream responseStream = StartWebRequest(GetAuthorURL(webUrl), methodData))
{
BufferedStream bufferedResponseStream = new
BufferedStream(responseStream, 4096);
string metaInfo = GetDocumentResponse(bufferedResponseStream);
bufferedResponseStream.CopyTo(outStream);
return ParseMetaInformationResponse(metaInfo);
}
}
private
static
string GetDocumentResponse(Stream responseStream)
{
if (null == responseStream)
{
throw
new
ArgumentException("responseStream is null");
}
string metaInfo = ExtractResponsePreamble(responseStream);
if (string.IsNullOrEmpty(metaInfo))
{
throw
new
FrontPageRPCException("unable to parse responseData");
}
CheckForInternalErrorMessage(metaInfo);
CheckForSuccessMessage(metaInfo);
return metaInfo;
}
public
string GetDocumentMetaInfoRaw(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "getDocsMetaInfo:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "");
methodData.Add("listHiddenDocs", "true");
methodData.Add("listLinkInfo", "false");
methodData.Add("validateWelcomeNames", "false");
methodData.Add("url_list", "[" + webUrl.FileUrl + "]");
return SendSimpleRequest(GetAuthorURL(webUrl), methodData);
}
public
DocumentInfo GetDocumentMetaInfo(WebUrl webUrl)
{
string response = GetDocumentMetaInfoRaw(webUrl);
DocumentInfo docInfo = ParseMetaInformationResponse(response);
return docInfo;
}
public
string GetDocumentHash(WebUrl webUrl)
{
string response = GetDocumentMetaInfoRaw(webUrl);
return HashUtil.GetHash(response);
}
public
List<WebUrl> ListFolders(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "list documents:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("listHiddenDocs", "true");
methodData.Add("listExplorerDocs", "false");
methodData.Add("listRecurse", "false");
methodData.Add("listFiles", "false");
methodData.Add("listFolders", "true");
methodData.Add("listLinkInfo", "true");
methodData.Add("listIncludeParent", "false");
methodData.Add("listDerived", "false");
methodData.Add("listBorders", "false");
methodData.Add("listChildWebs", "false");
methodData.Add("initialUrl", webUrl.FileUrl);
string response = SendSimpleRequest(GetAuthorURL(webUrl), methodData);
return ParseFileList(webUrl.SiteUrl, response, "url");
}
public
string ListWebs(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "get manifest:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("options", "structure,files,userlists,list_data,globallists,subscriptions, discussions,userinfo,webparts,security,nontemplatizable_data");
// methodData.Add("options", "[structure]");
return SendSimpleRequest(GetAuthorURL(webUrl), methodData);
// return ParseWebList(webUrl.SiteUrl, response, "url");
}
public
List<WebUrl> ListDocuments(WebUrl webUrl, bool recursive)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "list documents:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("listHiddenDocs", "true");
methodData.Add("listExplorerDocs", "false");
methodData.Add("listRecurse", recursive ? "true" : "false");
methodData.Add("listFiles", "true");
methodData.Add("listFolders", "false");
methodData.Add("listLinkInfo", "false");
methodData.Add("listIncludeParent", "false");
methodData.Add("listDerived", "false");
methodData.Add("listBorders", "false");
methodData.Add("listChildWebs", "true");
methodData.Add("initialUrl", webUrl.FileUrl);
string response = SendSimpleRequest(GetAuthorURL(webUrl), methodData);
return ParseFileList(webUrl.SiteUrl, response, "document_name");
}
private
static
List<WebUrl> ParseFileList(string siteUrl, string responseData, string attributeName)
{
Regex fileMatchRegEx = new
Regex(@"\<li\>" + attributeName + @"=(?<name>.*?)\n\<li\>", RegexOptions.Compiled | RegexOptions.Singleline);
List<WebUrl> aRet = new
List<WebUrl>();
MatchCollection fileInfoMatches = fileMatchRegEx.Matches(responseData);
foreach (Match m in fileInfoMatches)
{
string fileUrl = HttpUtility.UrlDecode(DecodeString(m.Groups["name"].Value));
aRet.Add(new
WebUrl { SiteUrl = siteUrl , FileUrl = fileUrl});
}
return aRet;
}
private
static
string DecodeString(string source)
{
if (!string.IsNullOrEmpty(source))
{
Regex rg = new
Regex("&#([0-9]{1,3});&#([0-9]{1,3});");
foreach (Match match in rg.Matches(source))
{
byte[] bytes = new[] { byte.Parse(match.Groups[1].Value), byte.Parse(match.Groups[2].Value) };
source = source.Replace(match.Value, Encoding.UTF8.GetString(bytes));
}
source = HttpUtility.HtmlDecode(source);
}
return source;
}
public
void CreateDirectory(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "create url-directories:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("urldirs", "[[url=" + webUrl.FileUrl + "]]");
string response = SendSimpleRequest(GetAuthorURL(webUrl), methodData);
CheckForSuccessMessage(response);
}
public
string GetServerExtensionsVersion(WebUrl siteUrl)
{
if (null == serverExtensionsVersion)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "server version:" + defaultServerVersion);
methodData.Add("service_name", "/");
string responseData = SendSimpleRequest(GetAuthorURL(siteUrl), methodData);
serverExtensionsVersion = ExtractServerExtensionsVersion(responseData);
}
return serverExtensionsVersion;
}
public
void CheckInDocument(WebUrl webUrl, string comment)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "checkin document: " + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("document_name", webUrl.FileUrl);
methodData.Add("comment", comment);
methodData.Add("keep_checked_out", "false");
SendSimpleRequest(GetAuthorURL(webUrl), methodData);
}
public
void CheckOutDocument(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "checkout document: " + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "/");
methodData.Add("document_name", webUrl.FileUrl);
methodData.Add("force", "0");
methodData.Add("timeout", "0");
SendSimpleRequest(GetAuthorURL(webUrl), methodData);
}
public
void UnCheckOutDocument(WebUrl webUrl)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "uncheckout document: " + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name","/");
methodData.Add("document_name", webUrl.FileUrl );
methodData.Add("force", "false");
SendSimpleRequest(GetAuthorURL(webUrl), methodData);
}
public
void PutDocument(WebUrl webUrl, Stream file)
{
PutDocument(webUrl, file, null);
}
public
void PutDocument(WebUrl webUrl, Stream file, DocumentPropertyCollection properties)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "put document:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "");
methodData.Add("put_option", "overwrite,createdir,migrationsemantics");
methodData.Add("keep_checked_out", "false");
using (Stream responseStream =
StartWebRequest(
GetAuthorURL(webUrl),
reqStream => WriteDocumentData(reqStream, webUrl.FileUrl, file, properties, methodData)
)
)
{
string response = GetResponseString(responseStream);
CheckForInternalErrorMessage(response);
CheckForSuccessMessage(response);
}
}
public
void SetDocumentMetaInfo(WebUrl webUrl, DocumentInfo docInfo)
{
NameValueCollection methodData = new
NameValueCollection();
methodData.Add("method", "setDocsMetaInfo:" + GetServerExtensionsVersion(webUrl));
methodData.Add("service_name", "");
methodData.Add("listHiddenDocs", "true");
methodData.Add("listLinkInfo", "true");
methodData.Add("url_list", "[" + webUrl.FileUrl + "]");
methodData.Add("metaInfoList", "[" + docInfo.GetMetaInfoList(false) + "]");
string responseData = SendSimpleRequest(GetAuthorURL(webUrl), methodData);
if (!SetMetaDataResponseSuccess(responseData))
{
throw
new
FrontPageRPCException("SetDocumentMetaInfo failed", webUrl.FileUrl);
}
}
private
static
bool SetMetaDataResponseSuccess(string responseString)
{
return responseString.IndexOf("method") > -1 && -1 == responseString.IndexOf("failedUrls");
}
private
static
void AddCollectionData(TextWriter tw, NameValueCollection data)
{
string separator = string.Empty;
foreach(string key in data)
{
tw.Write(separator);
tw.Write("{0}={1}", key, HttpUtility.UrlEncode(data[key]));
separator = "&";
}
}
private
static
void CheckForInternalErrorMessage(string response)
{
|