internal static string EncodeUriCharacters(string text) { StringBuilder result = null; int start = 0; for (int i = 0; i < text.Length; ++i) { if (text[i] >= 127) { if (result == null) { result = new StringBuilder(); } result.Append(text, start, i - start); result.Append(XUri.Encode(text[i].ToString())); start = i + 1; } } if (result != null) { result.Append(text, start, text.Length - start); return(result.ToString()); } return(text); }
public override User GetUser(string user) { User u = null; DreamMessage response = _dekiPlug.At("users", "=" + XUri.Encode(user)).GetAsync().Wait(); if (response.IsSuccessful) { XDoc userDoc = response.ToDocument(); string email = userDoc["email"].AsText; List <Group> groups = new List <Group>(); groups.Add(new Group(REMOTEDEKIUSERS)); foreach (XDoc groupDoc in userDoc["groups/group"]) { string groupName = groupDoc["groupname"].AsText; if (!string.IsNullOrEmpty(groupName)) { groups.Add(new Group(groupName)); } } u = new User(user, email, groups.ToArray()); } else { throw new DreamAbortException(response); } return(u); }
public void TestAttachmentDescriptionAssociations() { DreamMessage msg = null; Plug p = Utils.BuildPlugForAdmin(); string pageId1, pageId2 = null; msg = PageUtils.CreateRandomPage(p, out pageId1); msg = PageUtils.CreateRandomPage(p, out pageId2); string description = null; string fileid = null; string filename = null; string propertyEtag = null; string propertyName = "urn:deki.mindtouch.com#description"; //Create initial file rev FileUtils.UploadRandomFile(p, pageId1, null, null, out fileid, out filename); //set initial file description description = "Content r1 on p1"; msg = p.At("files", fileid, "properties").WithHeader("Slug", XUri.Encode(propertyName)).PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, description)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "POST property got non 200"); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, description, "Contents don't match!"); propertyEtag = msg.ToDocument()["/property/@etag"].AsText; //Validate intitial file description msg = p.At("files", fileid, "info").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "GET file info returned non 200:" + msg.ToString()); Assert.AreEqual(description, msg.ToDocument()["description"].AsText, "Unexpected description"); //update file description description = "Content r1 on p1 updated description 1"; msg = p.At("files", fileid, "properties", XUri.DoubleEncode(propertyName)).WithHeader(DreamHeaders.ETAG, propertyEtag).PutAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, description)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "PUT property got non 200"); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, description, "Contents don't match!"); propertyEtag = msg.ToDocument()["/property/@etag"].AsText; //New file revision msg = p.At("pages", pageId1, "files", "=" + filename).PutAsync(DreamMessage.Ok(MimeType.ANY_TEXT, "Some content")).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "File upload failed: " + msg.ToString()); //Updated file description description = "Content r2 on p1"; msg = p.At("files", fileid, "properties", XUri.DoubleEncode(propertyName)).WithHeader(DreamHeaders.ETAG, propertyEtag).PutAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, description)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "PUT property got non 200"); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, description, "Contents don't match!"); propertyEtag = msg.ToDocument()["/property/@etag"].AsText; //Move file msg = p.At("files", fileid, "move").With("to", pageId2).Post(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "File move failed:" + msg.ToString()); //Update file description description = "Content r2 on p2"; msg = p.At("files", fileid, "properties", XUri.DoubleEncode(propertyName)).WithHeader(DreamHeaders.ETAG, propertyEtag).PutAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, description)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "PUT property got non 200"); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, description, "Contents don't match!"); propertyEtag = msg.ToDocument()["/property/@etag"].AsText; }
public void PutFileProperties() { Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); string propertyContent = Utils.GetSmallRandomText(); string propertyName = Utils.GenerateUniqueName(); string fileid = null; msg = FileUtils.UploadRandomFile(p, id, out fileid); msg = p.At("files", fileid, "properties").WithHeader("Slug", XUri.Encode(propertyName)).PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, propertyContent)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, propertyContent, "Contents don't match!"); msg = p.At("files", fileid, "properties", propertyName).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Non 200 status on get:property content: " + msg.ToString()); Assert.AreEqual(propertyContent, msg.AsText(), "Contents don't match!"); PageUtils.DeletePageByID(p, id, true); }
public void PostPutDeleteSiteProperties() { Plug p = Utils.BuildPlugForAdmin(); string propertyContent = Utils.GetSmallRandomText(); string propertyName = Utils.GenerateUniqueName(); DreamMessage msg = null; try { msg = p.At("site", "properties").WithHeader("Slug", XUri.Encode(propertyName)).PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, propertyContent)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "POST property got non 200"); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, propertyContent, "Contents don't match!"); msg = p.At("site", "properties", propertyName).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "GET property returned non 200"); Assert.AreEqual(propertyContent, msg.AsText(), "Contents don't match!"); propertyContent = Utils.GetSmallRandomText(); msg = p.At("site", "properties", propertyName).WithHeader(DreamHeaders.ETAG, msg.Headers.ETag).PutAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, propertyContent)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "PUT property returned non 200"); msg = p.At("site", "properties", propertyName).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "GET property returned non 200"); Assert.AreEqual(propertyContent, msg.AsText(), "Contents don't match on second rev!"); } finally { msg = p.At("site", "properties", propertyName).DeleteAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Delete status non 200"); } msg = p.At("site", "properties", propertyName).GetAsync().Wait(); Assert.AreEqual(DreamStatus.NotFound, msg.Status, "Deleted property get status non 404"); }
public void SaveGetPageProperty() { Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); string content = Utils.GetSmallRandomText(); //NOTE: PUT: resource/{properties}/{key} is allowing property creation. Creating properties this way is undocumented and not recommended but was added for import/export //Test property creation via PUT //msg = p.At("pages", id, "properties", "foo").PutAsync(DreamMessage.Ok(MimeType.TEXT, content)).Wait(); //Assert.AreEqual(DreamStatus.Conflict, msg.Status); msg = p.At("pages", id, "properties").WithHeader("Slug", XUri.Encode("foo")).PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, content)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "post properties returned non 200 status: " + msg.ToString()); //TODO: validate response XML for 200's msg = p.At("pages", id, "properties", "foo", "info").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property returned non 200 status: " + msg.ToString()); Assert.AreEqual(content, msg.ToDocument()["/property[@name= 'foo']/contents"].AsText, "Contents don't match!"); XUri contentsUri = msg.ToDocument()["/property[@name = 'foo']/contents/@href"].AsUri; Assert.IsTrue(contentsUri != null, "Couldn't find content href"); Plug p2 = Plug.New(contentsUri).WithTimeout(p.Timeout).WithHeaders(p.Headers).WithCredentials(p.Credentials); msg = p2.GetAsync().Wait(); Assert.IsTrue(msg.Status == DreamStatus.Ok, "get property contents by uri didnt return status 200: " + msg.ToString()); Assert.IsTrue(msg.ContentType.Match(MimeType.TEXT), "get property content type didnt match: " + msg.ToString()); Assert.IsTrue(msg.AsText() == content, "get property content didnt match: " + msg.ToString()); }
public Result <Stream> GetConvertedScore(string scoreId, string fileName, Result <Stream> aResult) { theServiceUri .At("scores", scoreId, XUri.Encode(fileName)) .Get(new Result <DreamMessage>()) .WhenDone(delegate(Result <DreamMessage> answer) { if (!answer.Value.IsSuccessful) { if (answer.Value.Status == DreamStatus.NotFound) { aResult.Return((Stream)null); } else { aResult.Throw(answer.Exception); } } else { aResult.Return(answer.Value.ToStream()); } } ); return(aResult); }
public static string AnchorEncode(string section) { return(XUri.Encode(section.Trim().Replace(' ', '_')).ReplaceAll( "%3A", ":", "%", "." )); }
public Yield FeatureGetAuthenticate(DreamContext context, DreamMessage request, Result <DreamMessage> response) { string user = Authenticate(context, request); string password; HttpUtil.GetAuthentication(context.Uri.ToUri(), request.Headers, out user, out password); yield return(context.Relay(Self.At("users", XUri.Encode(user)).WithCredentials(user, password), request, response)); }
public static Plug With(this Plug aPlug, ChangeOptions aChangeOptions) { switch (aChangeOptions.Feed) { case ChangeFeed.LongPoll: case ChangeFeed.Normal: aPlug = aPlug.With(Constants.FEED, Constants.FEED_NORMAL); break; case ChangeFeed.Continuous: aPlug = aPlug.With(Constants.FEED, Constants.FEED_CONTINUOUS); break; default: //Never get here break; } if (!String.IsNullOrEmpty(aChangeOptions.Filter)) { aPlug = aPlug.With(Constants.FILTER, XUri.Encode(aChangeOptions.Filter)); } if (!String.IsNullOrEmpty(aChangeOptions.View)) { aPlug = aPlug.With(Constants.FILTER, XUri.Encode(Constants.VIEW)); aPlug = aPlug.With(Constants.VIEW_PARAMETER, aChangeOptions.View); } if (aChangeOptions.Heartbeat.HasValue) { aPlug = aPlug.With(Constants.HEARTBEAT, aChangeOptions.Heartbeat.Value); } if (aChangeOptions.IncludeDocs.HasValue) { aPlug = aPlug.With(Constants.INCLUDE_DOCS, aChangeOptions.IncludeDocs.Value ? "true" : "false"); } if (aChangeOptions.Limit.HasValue) { aPlug = aPlug.With(Constants.LIMIT, aChangeOptions.Limit.Value); } if (aChangeOptions.Since.HasValue) { aPlug = aPlug.With(Constants.SINCE, aChangeOptions.Since.Value); } if (aChangeOptions.Timeout.HasValue) { aPlug = aPlug.With(Constants.TIMEOUT, aChangeOptions.Timeout.Value); } return(aPlug); }
//--- Methods --- /// <summary> /// Convert to Content-Disposition header string. /// </summary> /// <returns></returns> public override string ToString() { StringBuilder result = new StringBuilder(); if (Inline) { result.Append("inline"); } else { result.Append("attachment"); } if (CreationDate != null) { result.Append("; creation-date=\"").Append(CreationDate.Value.ToUniversalTime().ToString("r")).Append("\""); } if (ModificationDate != null) { result.Append("; modification-date=\"").Append(ModificationDate.Value.ToUniversalTime().ToString("r")).Append("\""); } if (!string.IsNullOrEmpty(FileName)) { bool gotFilename = false; if (!string.IsNullOrEmpty(UserAgent)) { if (URL_ENCODE_REGEX.IsMatch(UserAgent)) { // Filename is uri encoded to support non ascii characters. // + is replaced with %20 for IE otherwise it saves names containing spaces with plusses. result.Append("; filename=\"").Append(XUri.Encode(FileName).Replace("+", "%20")).Append("\""); gotFilename = true; } else if (MIME_ENCODE_REGEX.IsMatch(UserAgent)) { result.Append("; filename=\"=?UTF-8?B?").Append(Convert.ToBase64String(Encoding.UTF8.GetBytes(FileName))).Append("?=\""); gotFilename = true; } } if (!gotFilename) { result.Append("; filename=\"").Append(Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(FileName))).Append("\""); } } if (Size != null) { result.Append("; size=").Append(Size.Value); } return(result.ToString()); }
public void DeleteAndOverwritePageProperty() { //Set a property foo with content c1 //Delete the property foo //Validate that foo doesn't exist //Set property to content c2 //Validate property content of c2 string C1 = "C1"; string C2 = "C2"; Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; XDoc content = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); //Set foo with c1 content = new XDoc("deltest").Start("somevalue").Value(C1).End(); msg = p.At("pages", id, "properties").WithHeader("Slug", XUri.Encode("foo")).PostAsync(DreamMessage.Ok(content)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "put property returned non 200 status: " + msg.ToString()); msg = p.At("pages", id, "properties", "foo", "info").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property returned non 200 status: " + msg.ToString()); msg = p.At("pages", id, "properties", "foo").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property contents returned non 200 status: " + msg.ToString()); Assert.AreEqual(content.ToPrettyString(), msg.ToDocument().ToPrettyString(), "Contents don't match!"); //Delete foo msg = p.At("pages", id, "properties", "foo").DeleteAsync(DreamMessage.Ok()).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "delete property returned non 200 status: " + msg.ToString()); //Validate that foo doesn't exist msg = p.At("pages", id, "properties", "foo", "info").GetAsync(DreamMessage.Ok()).Wait(); Assert.AreEqual(DreamStatus.NotFound, msg.Status, "get deleted property returned non 404 status: " + msg.ToString()); //Set property to content c2 content = new XDoc("deltest").Start("somevalue").Value(C2).End(); msg = p.At("pages", id, "properties").WithHeader("Slug", XUri.Encode("foo")).PostAsync(DreamMessage.Ok(content)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "put property returned non 200 status: " + msg.ToString()); msg = p.At("pages", id, "properties", "foo", "info").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property returned non 200 status: " + msg.ToString()); //Validate property content of c2 msg = p.At("pages", id, "properties", "foo").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property contents returned non 200 status: " + msg.ToString()); Assert.AreEqual(content.ToPrettyString(), msg.ToDocument().ToPrettyString(), "Contents don't match!"); }
public void PostUserProperties() { Plug p = Utils.BuildPlugForAdmin(); string id = null; DreamMessage msg = UserUtils.CreateRandomContributor(p, out id); string propertyContent = Utils.GetSmallRandomText(); string propertyName = Utils.GenerateUniqueName(); msg = p.At("users", id, "properties").WithHeader("Slug", XUri.Encode(propertyName)).PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, propertyContent)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status); Assert.AreEqual(msg.ToDocument()["/property/contents"].AsText, propertyContent, "Contents don't match!"); msg = p.At("users", id, "properties", propertyName).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status); Assert.AreEqual(propertyContent, msg.AsText(), "Contents don't match!"); }
public void GetDateTag() { // 1. Create random page // 2. Generate random date tag and attach to page // (3a) Assert retrived tag value equals to that of generated string // (3b) Assert tag exists according to tag ID // (4a) Same as 3a, but using the tag value in the path // (4b) Same as 3b, but using the tag value in the path // 5. Delete page Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); DateTime date = DateTime.UtcNow; string value = "date:" + date.ToString("yyyy-MM-dd"); XDoc tagsDoc = new XDoc("tags") .Start("tag").Attr("value", value).End(); DreamMessage tempmsg = p.At("pages", id, "tags").Put(tagsDoc); Assert.IsTrue(tempmsg.Status == DreamStatus.Ok, "PUT request failed"); // GET:site/tags/{id} uint tag_id = tempmsg.ToDocument()["tag/@id"].AsUInt ?? 0; msg = p.At("site", "tags", tag_id.ToString()).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, String.Format("GET request failed! TAG_ID: {0} ||| PUT_MSG: {1} ||| GET_MSG: {2} ||| value: {3}", tag_id, tempmsg.ToString(), msg.ToString(), value)); Assert.IsTrue(msg.ToDocument()["@value"].AsText == value, "Tag value does not match generated string! {id}"); Assert.IsFalse(msg.ToDocument()[string.Format("pages/page[@id=\"{0}\"]", id)].IsEmpty, "Tag with specified ID does not exist! {id}"); // GET:site/tags/{=tag_value} msg = p.At("site", "tags", string.Format("={0}", XUri.Encode(value))).Get(); Assert.IsTrue(msg.Status == DreamStatus.Ok, "GET request failed! {=tag_value}"); Assert.IsTrue(msg.ToDocument()["@value"].AsText == value, "Tag value does not match generated string! {=tag_value}"); Assert.IsFalse(msg.ToDocument()[string.Format("pages/page[@id=\"{0}\"]", id)].IsEmpty, "Tag with specified ID does not exist! {=tag_value}"); PageUtils.DeletePageByID(p, id, true); }
public override Group GetGroup(string group) { Group g = null; DreamMessage response = _dekiPlug.At("groups", "=" + XUri.Encode(group)).GetAsync().Wait(); if (response.IsSuccessful) { XDoc groupDoc = response.ToDocument(); string groupName = groupDoc["groupname"].AsText; if (!string.IsNullOrEmpty(groupName)) { g = new Group(groupName); } } else { throw new DreamAbortException(response); } return(g); }
public void GetTextTag() { // 1. Create random page // 2. Generate random text tag and attach to page // (3a) Assert retrived tag value equals to that of generated string // (3b) Assert tag exists according to tag ID // (4a) Same as 3a, but using the tag value in the path // (4b) Same as 3b, but using the tag value in the path // 5. Delete page Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); Guid guid = Guid.NewGuid(); XDoc tagsDoc = new XDoc("tags") .Start("tag").Attr("value", guid.ToString()).End(); msg = p.At("pages", id, "tags").Put(tagsDoc); Assert.IsTrue(msg.Status == DreamStatus.Ok, "PUT request failed"); // GET:site/tags/{id} uint tag_id = msg.ToDocument()["tag/@id"].AsUInt ?? 0; msg = p.At("site", "tags", tag_id.ToString()).Get(); Assert.IsTrue(msg.Status == DreamStatus.Ok, "GET request failed {id}"); Assert.IsTrue(msg.ToDocument()["@value"].AsText == guid.ToString(), "Tag value does not match generated string! {id}"); Assert.IsFalse(msg.ToDocument()[string.Format("pages/page[@id=\"{0}\"]", id)].IsEmpty, "Tag with specified ID does not exist! {id}"); // GET:site/tags/{=tag_value} msg = p.At("site", "tags", string.Format("={0}", XUri.Encode(guid.ToString()))).Get(); Assert.IsTrue(msg.Status == DreamStatus.Ok, "GET request failed {=tag_value}"); Assert.IsTrue(msg.ToDocument()["@value"].AsText == guid.ToString(), "Tag value does not match generated string! {=tag_value}"); Assert.IsFalse(msg.ToDocument()[string.Format("pages/page[@id=\"{0}\"]", id)].IsEmpty, "Tag with specified ID does not exist! {=tag_value}"); PageUtils.DeletePageByID(p, id, true); }
public void NewPropertyWithEtagNegative() { Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); XDoc doc = new XDoc("properties"); string contentShort = "Some content"; doc.Start("property").Attr("name", "prop_short").Attr("etag", "some-unexpected-etag") .Start("contents").Attr("type", MimeType.TEXT.ToString()) .Value(contentShort) .End() .End(); msg = p.At("pages", id, "properties").PutAsync(DreamMessage.Ok(doc)).Wait(); Assert.AreEqual(DreamStatus.MultiStatus, msg.Status, "put batch property returned 200 status but expected MultiStatus"); Assert.AreEqual("409", msg.ToDocument()["/properties/property[@name='prop_short']/status/@code"].AsText); msg = p.At("pages", id, "properties").WithHeader("Slug", XUri.Encode("foo")).WithHeader(DreamHeaders.ETAG, "some-etag").PostAsync(DreamMessage.Ok(MimeType.TEXT, "blah")).Wait(); Assert.AreEqual(DreamStatus.Conflict, msg.Status, "put batch property returned 200 status but expected : " + msg.ToString()); }
public void MultiplePropertiesInPage() { //Save multiple properties in a page //Retrieve them Plug p = Utils.BuildPlugForAdmin(); string id = null; string path = null; int NUMPROPS = 5; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); for (int i = 1; i <= NUMPROPS; i++) { string propname = string.Format("testprop_{0}", i); XDoc content = new XDoc("proptest"); content.Start("name").Value(propname).End(); msg = p.At("pages", id, "properties").WithHeader("Slug", XUri.Encode(propname)).PostAsync(DreamMessage.Ok(content)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "put property returned non 200 status: " + msg.ToString()); msg = p.At("pages", id, "properties", propname, "info").GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property returned non 200 status: " + msg.ToString()); Assert.AreEqual(MimeType.XML.ToString(), MimeType.New(msg.ToDocument()["/property[@name='" + propname + "']/contents/@type"].AsText).ToString(), "Content types dont match"); msg = p.At("pages", id, "properties", propname).GetAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get property content returned non 200 status: " + msg.ToString()); Assert.AreEqual(content.ToPrettyString(), msg.ToDocument().ToPrettyString(), "Contents don't match!"); //revisions not yet supported. //Assert.AreEqual((msg.ToDocument()["/property[@name= '" + propname + "']/revisions/@count"].AsInt ?? 0), 1); } msg = p.At("pages", id, "properties").GetAsync(DreamMessage.Ok()).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "get properties returned non 200 status: " + msg.ToString()); Assert.AreEqual(msg.ToDocument()["/properties/@count"].AsInt, NUMPROPS, "Wrong property count!"); }
public static string UriEncode( [DekiScriptParam("text to encode")] string text ) { return(XUri.Encode(text)); }
public string AnchorEncode( [DekiExtParam("section anchor name")] string section ) { return(XUri.Encode(section.Trim().Replace(' ', '_')).ReplaceAll("%3A", ":", "%", ".")); }
//--- Methods --- private XDoc PerformQuery(XUri dataservice, string resource, string expand, string filter, string orderby, int?skip, int?top, bool fetchSchema, out XDoc schema) { Plug p = _adoNetPlug; if (dataservice != null) { p = Plug.New(dataservice); } else if (p == null) { throw new ArgumentException("Missing field", "dataservice"); } if (fetchSchema) { schema = FetchSchema(p); } else { schema = null; } if (!string.IsNullOrEmpty(resource)) { //HACKHACKHACK: +'s aren't treated the same way as '%20' when uri is decoded on the server side string s = XUri.Encode(resource).Replace("+", "%20"); p = p.At(s); } if (!string.IsNullOrEmpty(expand)) { p = p.With("$expand", expand); } if (!string.IsNullOrEmpty(filter)) { p = p.With("$filter", filter); } if (!string.IsNullOrEmpty(orderby)) { p = p.With("$orderby", orderby); } if (skip != null) { p = p.With("$skip", skip.Value); } if (top != null) { p = p.With("$top", top.Value); } XDoc ret = null; string key = p.ToString(); lock (_cache) { _cache.TryGetValue(key, out ret); } if (ret == null) { ret = p.Get().ToDocument(); // add result to cache and start a clean-up timer lock (_cache) { _cache[key] = ret; } TaskTimer.New(TimeSpan.FromSeconds(CACHE_TTL), RemoveCachedEntry, key, TaskEnv.None); } return(ret); }
public static UserBE BuildUserFromAuthService(ServiceBE serviceInfo, UserBE knownUser, string usernameToBuild, bool bypassAuthentication, string authusername, string password, out List <GroupBE> externalGroups) { externalGroups = null; if (serviceInfo == null || string.IsNullOrEmpty(usernameToBuild)) { return(null); } //Dont perform external lookup for disabled users if (knownUser != null && !knownUser.UserActive) { return(knownUser); } var errMsg = DekiResources.UNABLE_TO_AUTH_WITH_SERVICE(serviceInfo.Type, serviceInfo.SID, serviceInfo.Uri); if (knownUser != null && !string.IsNullOrEmpty(knownUser.ExternalName)) { usernameToBuild = knownUser.ExternalName; } UserBE ret = null; DreamMessage response = null; if (serviceInfo.Uri == null) { throw new ExternalServiceNotStartedFatalException(serviceInfo.Type, serviceInfo.SID); } try { Plug dekiExternalAuthPlug; //bypassAuthentication is used when you only need user details but not to necessarily authenticate if (bypassAuthentication) { //An external auth service's GET: user/{username} does not necessarily require authentication to lookup users but it may. It's up to the service //to decide if anon requests are allowed. dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(USER_INFO).At(XUri.Encode(usernameToBuild)); } else { //Credentials are always needed for GET: authenticate. The user details of the auth'd user is returned with same format as GET: user/{username} dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(AUTHENTICATE_PATH); } //Always include credentials with the request if they're supplied if (!string.IsNullOrEmpty(authusername)) { dekiExternalAuthPlug = dekiExternalAuthPlug.WithCredentials(authusername, password ?? string.Empty); } response = dekiExternalAuthPlug.GetAsync().Wait(); } catch (Exception x) { throw new ExternalServiceResponseException(errMsg, DreamMessage.InternalError(x)); } if (response.IsSuccessful) { XDoc userXml = response.ToDocument(); if (userXml == null || userXml.IsEmpty) { throw new ExternalAuthResponseFatalException(); } string nameFromAuthProvider = userXml["@name"].Contents; if (!nameFromAuthProvider.EqualsInvariantIgnoreCase(usernameToBuild)) { throw new ExternalServiceUnexpecteUsernameFatalException(userXml["@name"].AsText, usernameToBuild); } ret = knownUser ?? new UserBE(); ret.Email = string.IsNullOrEmpty(userXml["email"].AsText) ? (ret.Email ?? string.Empty) : userXml["email"].AsText; //Build the realname (exposed as 'fullname' in user xml) by saving it as '{firstname} {lastname}' string externalFirstName = userXml["firstname"].AsText ?? string.Empty; string externalLastName = userXml["lastname"].AsText ?? string.Empty; string separator = externalLastName.Length > 0 && externalFirstName.Length > 0 ? ", " : string.Empty; // NOTE (maxm): Fullname sync is disabled for now. Refer to bug 7855 #if !DISABLE_REAL_NAME_SYNCHRONIZATION ret.RealName = string.Format("{0}{1}{2}", externalLastName, separator, externalFirstName); #endif ret.ServiceId = serviceInfo.Id; ret.Touched = DateTime.UtcNow; ret.ExternalName = string.IsNullOrEmpty(ret.ExternalName) ? nameFromAuthProvider : ret.ExternalName; ret.Name = string.IsNullOrEmpty(ret.Name) ? nameFromAuthProvider : ret.Name; //For new users, the name must be normalized and unique if (ret.ID == 0) { string nameFromExternalName = string.Empty; //Allow using a displayname from an external provider only for new accounts if (!userXml["@displayname"].IsEmpty) { nameFromExternalName = userXml["@displayname"].AsText; } else { nameFromExternalName = ret.ExternalName; } ret.Name = UserBL.NormalizeExternalNameToWikiUsername(nameFromExternalName); } //Build group objects out of the user's group membership list externalGroups = new List <GroupBE>(); IList <GroupBE> userGroups = DbUtils.CurrentSession.Groups_GetByUser(ret.ID); //Preserve local groups for existing users if (ret.ID != 0 && userGroups != null) { foreach (GroupBE g in userGroups) { if (ServiceBL.IsLocalAuthService(g.ServiceId)) { externalGroups.Add(g); } } } foreach (XDoc group in userXml["groups/group"]) { GroupBE g = new GroupBE(); g.Name = group["@name"].AsText; g.ServiceId = serviceInfo.Id; if (!string.IsNullOrEmpty(g.Name)) { externalGroups.Add(g); } } } else { switch (response.Status) { case DreamStatus.Unauthorized: if (bypassAuthentication) { DekiContext.Current.Instance.Log.Warn(string.Format("Attempted to lookup user info on auth provider '{0}' but failed since it required credentials", serviceInfo.Id)); } throw new ExternalServiceAuthenticationDeniedException(DekiWikiService.AUTHREALM, serviceInfo.Description); default: throw new ExternalServiceResponseException(errMsg, response); } } return(ret); }
public static GroupBE BuildGroupFromAuthService(ServiceBE serviceInfo, GroupBE knownGroup, string groupNameToBuild, string authusername, string password) { if (serviceInfo == null || string.IsNullOrEmpty(groupNameToBuild)) { return(null); } GroupBE ret = null; DreamMessage response = null; if (serviceInfo.Uri == null) { throw new ExternalServiceNotStartedFatalException(serviceInfo.Type, serviceInfo.SID); } var errMsg = DekiResources.GROUP_DETAILS_LOOKUP_FAILED(groupNameToBuild); try { Plug dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(GROUP_INFO).At(XUri.Encode(groupNameToBuild)); //Always include credentials with the request if they're supplied if (!string.IsNullOrEmpty(authusername)) { dekiExternalAuthPlug = dekiExternalAuthPlug.WithCredentials(authusername, password ?? string.Empty); } response = dekiExternalAuthPlug.GetAsync().Wait(); } catch (Exception x) { throw new ExternalServiceResponseException(errMsg, DreamMessage.InternalError(x)); } if (response.IsSuccessful) { XDoc groupXml = response.ToDocument(); if (groupXml.HasName("group") && groupXml["@name"].Contents.EqualsInvariant(groupNameToBuild)) { if (knownGroup == null) { ret = new GroupBE(); } else { ret = knownGroup; } ret.Name = string.IsNullOrEmpty(ret.Name) ? groupNameToBuild : ret.Name; ret.ServiceId = serviceInfo.Id; } //TODO (MaxM): Consider looking up existing wiki users and associating them here. } else { switch (response.Status) { case DreamStatus.Unauthorized: throw new ExternalServiceAuthenticationDeniedException(DekiWikiService.AUTHREALM, serviceInfo.Description); case DreamStatus.InternalError: case DreamStatus.Forbidden: default: throw new ExternalServiceResponseException(errMsg, response); } } return(ret); }