// * Redeem upload token // Implements http://www.23developer.com/api/photo-redeem-upload-token public bool RedeemUploadToken(string filename, string fileContentType, System.IO.Stream filestream, string uploadToken) { // Verify required parameters if (filestream == null) { return(false); } // Ensure that only relative filenames are sent int relativeFilenameSplit = filename.LastIndexOf('\\'); string relativeFilename = (relativeFilenameSplit == -1 ? filename : filename.Substring(relativeFilenameSplit + 1)); // Build request URL List <MultipartPostPart> data = new List <MultipartPostPart> { MultipartPostPart.CreateFormFilePart("file", relativeFilename, fileContentType, filestream), MultipartPostPart.CreateFormPart("upload_token", uploadToken) }; // Do the request MessageReceivingEndpoint requestMessage = new MessageReceivingEndpoint(_provider.GetRequestUrl("/api/photo/redeem-upload-token", null), HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest); XPathNavigator responseMessage = _provider.DoRequest(requestMessage, data); if (responseMessage == null) { return(false); } // If nothing pops up, we'll return null return(true); }
public void PostMultipart() { var httpHandler = new TestWebRequestHandler(); bool callbackTriggered = false; httpHandler.Callback = req => { Match m = Regex.Match(req.ContentType, "multipart/form-data; boundary=(.+)"); Assert.IsTrue(m.Success, "Content-Type HTTP header not set correctly."); string boundary = m.Groups[1].Value; boundary = boundary.Substring(0, boundary.IndexOf(';')); // trim off charset string expectedEntity = "--{0}\r\nContent-Disposition: form-data; name=\"a\"\r\n\r\nb\r\n--{0}--\r\n"; expectedEntity = string.Format(expectedEntity, boundary); string actualEntity = httpHandler.RequestEntityAsString; Assert.AreEqual(expectedEntity, actualEntity); callbackTriggered = true; Assert.AreEqual(req.ContentLength, actualEntity.Length); IncomingWebResponse resp = new CachedDirectWebResponse(); return(resp); }; var request = (HttpWebRequest)WebRequest.Create("http://someserver"); var parts = new[] { MultipartPostPart.CreateFormPart("a", "b"), }; request.PostMultipart(httpHandler, parts); Assert.IsTrue(callbackTriggered); }
// * Replace photo // Implements http://www.23developer.com/api/photo-replace /// <summary> /// Replace a photo thumbnail given an id /// </summary> /// <param name="photoId">Id of photo</param> /// <param name="filename">The original filename</param> /// <param name="fileContentType">The meta content type of the file</param> /// <param name="filestream">An input stream for reading the file</param> /// <returns></returns> public bool Replace(int photoId, string filename, string fileContentType, System.IO.Stream filestream) { // Build request URL List <string> requestUrlParameters = new List <string>(); // Ensure that only relative filenames are sent int relativeFilenameSplit = filename.LastIndexOf('\\'); string relativeFilename = (relativeFilenameSplit == -1 ? filename : filename.Substring(relativeFilenameSplit + 1)); // Do the request MessageReceivingEndpoint requestMessage = new MessageReceivingEndpoint(_provider.GetRequestUrl("/api/photo/replace", requestUrlParameters), HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest); List <MultipartPostPart> data = new List <MultipartPostPart> { MultipartPostPart.CreateFormPart("photo_id", photoId.ToString()), MultipartPostPart.CreateFormFilePart("file", relativeFilename, fileContentType, filestream) }; XPathNavigator responseMessage = _provider.DoRequest(requestMessage, data); if (responseMessage == null) { return(false); } // If nothing pops up, we'll return true return(true); }
// * Update photo // Implements /// <summary>Update a photo given the id</summary> public bool Update(int photoId, int?albumId = null, string title = null, string description = null, string tags = null, bool?published = null, Dictionary <string, string> variables = null) { // Build request URL List <MultipartPostPart> data = new List <MultipartPostPart> { MultipartPostPart.CreateFormPart("photo_id", photoId.ToString()) }; if (albumId != null) { data.Add(MultipartPostPart.CreateFormPart("album_id", albumId.ToString())); } if (title != null) { data.Add(MultipartPostPart.CreateFormPart("title", title)); } if (description != null) { data.Add(MultipartPostPart.CreateFormPart("description", description)); } if (tags != null) { data.Add(MultipartPostPart.CreateFormPart("tags", tags)); } if (published != null) { data.Add(MultipartPostPart.CreateFormPart("publish", published.Value ? "1" : "0")); } if (variables != null) { foreach (KeyValuePair <string, string> entry in variables) { // Can't overwrite default values using this! if (!_defaultAttributes.Contains(entry.Key)) { data.Add(MultipartPostPart.CreateFormPart(entry.Key, entry.Value)); } else { throw new MalformedRequest("Cannot set built-in field '" + entry.Key + "' through custom variables."); } } } // Do the request MessageReceivingEndpoint requestMessage = new MessageReceivingEndpoint(_provider.GetRequestUrl("/api/photo/update", null), HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest); XPathNavigator responseMessage = _provider.DoRequest(requestMessage, data); if (responseMessage == null) { return(false); } // If nothing pops up, we'll return null return(true); }
public void FileSerializeMatchesLength() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension(".txt"); File.WriteAllText(file, "sometext"); var part = MultipartPostPart.CreateFormFilePart("someformname", file, "text/plain"); VerifyLength(part); } }
public static XDocument UpdateProfileImage(ConsumerBase twitter, string accessToken, Stream image, string contentType) { var parts = new[] { MultipartPostPart.CreateFormFilePart("image", "twitterPhoto", contentType, image), }; HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileImageEndpoint, accessToken, parts); IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request); string responseString = response.GetResponseReader().ReadToEnd(); return(XDocument.Parse(responseString)); }
public void MultiPartPostMultiByteCharacters() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension("txt"); File.WriteAllText(file, "\x1020\x818"); this.VerifyFullPost(new List <MultipartPostPart> { MultipartPostPart.CreateFormPart("a", "\x987"), MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"), }); } }
public void MultiPartPostAscii() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension("txt"); File.WriteAllText(file, "sometext"); this.VerifyFullPost(new List <MultipartPostPart> { MultipartPostPart.CreateFormPart("a", "b"), MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"), }); } }
public static XDocument UpdateProfileBackgroundImage(ConsumerBase twitter, string accessToken, string image, bool tile) { var parts = new[] { MultipartPostPart.CreateFormFilePart("image", image, "image/" + Path.GetExtension(image).Substring(1).ToLowerInvariant()), MultipartPostPart.CreateFormPart("tile", tile.ToString().ToLowerInvariant()), }; HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileBackgroundImageEndpoint, accessToken, parts); request.ServicePoint.Expect100Continue = false; IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request); string responseString = response.GetResponseReader().ReadToEnd(); return(XDocument.Parse(responseString)); }
private static void VerifyLength(MultipartPostPart part) { Contract.Requires(part != null); var expectedLength = part.Length; var ms = new MemoryStream(); var sw = new StreamWriter(ms); part.Serialize(sw); sw.Flush(); var actualLength = ms.Length; Assert.AreEqual(expectedLength, actualLength); }
/// <summary> /// Updates the authenticating user's status, also known as tweeting. /// </summary> /// <param name="twitter"></param> /// <param name="accessToken"></param> /// <param name="status">The text of your status update, typically up to 140 characters. URL encode as necessary. t.co link wrapping may effect character counts.</param> /// <param name="includeEntities">When set to either true, t or 1, each tweet will include a node called "entities,". This node offers a variety of metadata about the tweet in a discreet structure, including: user_mentions, urls, and hashtags. While entities are opt-in on timelines at present, they will be made a default component of output in the future. See Tweet Entities for more detail on entities. /// </param> /// <returns></returns> public static JObject UpdateStatus(ConsumerBase twitter, string accessToken, String status, bool includeEntities) { var parts = new[] { MultipartPostPart.CreateFormPart("status", status), MultipartPostPart.CreateFormPart("include_entities", includeEntities.ToString()), }; HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateStatusEndpoint, accessToken, parts); IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request); using (var responseReader = response.GetResponseReader()) { var result = responseReader.ReadToEnd(); return(JObject.Parse(result)); } }
// * Get upload token // Implements http://www.23developer.com/api/photo-get-upload-token public Domain.PhotoUploadToken GetUploadToken(string returnUrl, bool?backgroundReturn, int?userId, int?albumId, string title, string description, string tags, bool?publish, int?validMinutes, int?maxUploads) { if (String.IsNullOrEmpty(returnUrl)) { return(null); } // Build request URL List <MultipartPostPart> data = new List <MultipartPostPart> { MultipartPostPart.CreateFormPart("return_url", returnUrl) }; if (backgroundReturn != null) { data.Add(MultipartPostPart.CreateFormPart("background_return_p", backgroundReturn.Value ? "1" : "0")); } if (userId != null) { data.Add(MultipartPostPart.CreateFormPart("user_id", userId.ToString())); } if (albumId != null) { data.Add(MultipartPostPart.CreateFormPart("album_id", albumId.ToString())); } if (title != null) { data.Add(MultipartPostPart.CreateFormPart("title", title)); } if (description != null) { data.Add(MultipartPostPart.CreateFormPart("description", description)); } if (tags != null) { data.Add(MultipartPostPart.CreateFormPart("tags", tags)); } if (publish != null) { data.Add(MultipartPostPart.CreateFormPart("publish", publish.Value ? "1" : "0")); } if (validMinutes != null) { data.Add(MultipartPostPart.CreateFormPart("valid_minutes", validMinutes.ToString())); } if (maxUploads != null) { data.Add(MultipartPostPart.CreateFormPart("max_uploads", maxUploads.ToString())); } // Do the request MessageReceivingEndpoint requestMessage = new MessageReceivingEndpoint(_provider.GetRequestUrl("/api/photo/get-upload-token", null), HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest); XPathNavigator responseMessage = _provider.DoRequest(requestMessage, data); if (responseMessage == null) { return(null); } // Get the token XPathNodeIterator tokenNode = responseMessage.Select("/response"); if (!tokenNode.MoveNext()) { return(null); } Domain.PhotoUploadToken uploadToken = new Domain.PhotoUploadToken { UploadToken = Helpers.GetNodeChildValue(tokenNode.Current, "upload_token"), Title = Helpers.GetNodeChildValue(tokenNode.Current, "title"), Description = Helpers.GetNodeChildValue(tokenNode.Current, "description"), Tags = Helpers.GetNodeChildValue(tokenNode.Current, "tags"), Publish = (Helpers.GetNodeChildValue(tokenNode.Current, "publish") == "1"), UserId = Helpers.ConvertStringToInteger(Helpers.GetNodeChildValue(tokenNode.Current, "user_id")), AlbumId = Helpers.ConvertStringToInteger(Helpers.GetNodeChildValue(tokenNode.Current, "album_id")), ValidMinutes = Helpers.ConvertStringToInteger(Helpers.GetNodeChildValue(tokenNode.Current, "valid_minutes")), ValidUntil = Helpers.ConvertStringToInteger(Helpers.GetNodeChildValue(tokenNode.Current, "valid_until")), ReturnURL = Helpers.GetNodeChildValue(tokenNode.Current, "return_url") }; // If nothing pops up, we'll return null return(uploadToken); }
// * Upload photo // Implements http://www.23developer.com/api/photo-upload public int?Upload(string filename, string fileContentType, System.IO.Stream filestream, int?userId = null, int?albumId = null, string title = null, string description = null, string tags = null, bool?publish = null, Dictionary <string, string> variables = null) { // Verify required parameters if (filestream == null) { return(null); } // Ensure that only relative filenames are sent int relativeFilenameSplit = filename.LastIndexOf('\\'); string relativeFilename = (relativeFilenameSplit == -1 ? filename : filename.Substring(relativeFilenameSplit + 1)); // Build request URL List <MultipartPostPart> data = new List <MultipartPostPart> { MultipartPostPart.CreateFormFilePart("file", HttpUtility.UrlEncode(relativeFilename), fileContentType, filestream) }; if (userId != null) { data.Add(MultipartPostPart.CreateFormPart("user_id", userId.ToString())); } if (albumId != null) { data.Add(MultipartPostPart.CreateFormPart("album_id", albumId.ToString())); } if (title != null) { data.Add(MultipartPostPart.CreateFormPart("title", title)); } if (description != null) { data.Add(MultipartPostPart.CreateFormPart("description", description)); } if (tags != null) { data.Add(MultipartPostPart.CreateFormPart("tags", tags)); } if (publish != null) { data.Add(MultipartPostPart.CreateFormPart("publish", publish.Value ? "1" : "0")); } if (variables != null) { foreach (KeyValuePair <string, string> entry in variables) { // Can't overwrite default values using this! if (!_defaultAttributes.Contains(entry.Key)) { data.Add(MultipartPostPart.CreateFormPart(entry.Key, entry.Value)); } else { throw new MalformedRequest("Cannot set built-in field '" + entry.Key + "' through custom variables."); } } } // Do the request MessageReceivingEndpoint requestMessage = new MessageReceivingEndpoint(_provider.GetRequestUrl("/api/photo/upload", null), HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest); XPathNavigator responseMessage = _provider.DoRequest(requestMessage, data); if (responseMessage == null) { return(null); } // Get the Photo id XPathNodeIterator photos = responseMessage.Select("/response/photo_id"); if ((photos.MoveNext()) && (photos.Current != null)) { return(Helpers.ConvertStringToInteger(photos.Current.Value)); } // If nothing pops up, we'll return null return(null); }
public void FilePartAsFile() { var part = MultipartPostPart.CreateFormFilePart("somename", "somefile", "plain/text", new MemoryStream()); Assert.AreEqual("file", part.ContentDisposition); }
public void FormDataSerializeMatchesLength() { var part = MultipartPostPart.CreateFormPart("a", "b"); VerifyLength(part); }
/// <summary> /// Prepares to send a request to the Service Provider via the Authorization header. /// </summary> /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param> /// <returns>The web request ready to send.</returns> /// <remarks> /// <para>If the message has non-empty ExtraData in it, the request stream is sent to /// the server automatically. If it is empty, the request stream must be sent by the caller.</para> /// <para>This method implements OAuth 1.0 section 5.2, item #1 (described in section 5.4).</para> /// </remarks> private HttpWebRequest InitializeRequestAsAuthHeader(IDirectedProtocolMessage requestMessage) { var dictionary = this.MessageDescriptions.GetAccessor(requestMessage); // copy so as to not modify original var fields = new Dictionary <string, string>(); foreach (string key in dictionary.DeclaredKeys) { fields.Add(key, dictionary[key]); } if (this.Realm != null) { fields.Add("realm", this.Realm.AbsoluteUri); } HttpWebRequest httpRequest; UriBuilder recipientBuilder = new UriBuilder(requestMessage.Recipient); bool hasEntity = HttpMethodHasEntity(GetHttpMethod(requestMessage)); if (!hasEntity) { MessagingUtilities.AppendQueryArgs(recipientBuilder, requestMessage.ExtraData); } httpRequest = (HttpWebRequest)WebRequest.Create(recipientBuilder.Uri); this.PrepareHttpWebRequest(httpRequest); httpRequest.Method = GetHttpMethod(requestMessage); httpRequest.Headers.Add(HttpRequestHeader.Authorization, MessagingUtilities.AssembleAuthorizationHeader(Protocol.AuthorizationHeaderScheme, fields)); if (hasEntity) { // WARNING: We only set up the request stream for the caller if there is // extra data. If there isn't any extra data, the caller must do this themselves. var requestMessageWithBinaryData = requestMessage as IMessageWithBinaryData; if (requestMessageWithBinaryData != null && requestMessageWithBinaryData.SendAsMultipart) { // Include the binary data in the multipart entity, and any standard text extra message data. // The standard declared message parts are included in the authorization header. var multiPartFields = new List <MultipartPostPart>(requestMessageWithBinaryData.BinaryData); multiPartFields.AddRange(requestMessage.ExtraData.Select(field => MultipartPostPart.CreateFormPart(field.Key, field.Value))); this.SendParametersInEntityAsMultipart(httpRequest, multiPartFields); } else { ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || requestMessageWithBinaryData.BinaryData.Count == 0, MessagingStrings.BinaryDataRequiresMultipart); if (requestMessage.ExtraData.Count > 0) { this.SendParametersInEntity(httpRequest, requestMessage.ExtraData); } else { // We'll assume the content length is zero since the caller may not have // anything. They're responsible to change it when the add the payload if they have one. httpRequest.ContentLength = 0; } } } return(httpRequest); }