xref: /aosp_15_r20/external/google-breakpad/src/common/mac/HTTPMultipartUpload.m (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle// Copyright 2006 Google LLC
2*9712c20fSFrederick Mayle//
3*9712c20fSFrederick Mayle// Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle// modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle// met:
6*9712c20fSFrederick Mayle//
7*9712c20fSFrederick Mayle//     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle// notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle//     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle// copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle// in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle// distribution.
13*9712c20fSFrederick Mayle//     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle// contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle// this software without specific prior written permission.
16*9712c20fSFrederick Mayle//
17*9712c20fSFrederick Mayle// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle#import "HTTPMultipartUpload.h"
30*9712c20fSFrederick Mayle
31*9712c20fSFrederick Mayle#import "GTMDefines.h"
32*9712c20fSFrederick Mayle#import "encoding_util.h"
33*9712c20fSFrederick Mayle
34*9712c20fSFrederick Mayle@interface HTTPMultipartUpload (PrivateMethods)
35*9712c20fSFrederick Mayle- (NSString*)multipartBoundary;
36*9712c20fSFrederick Mayle// Each of the following methods will append the starting multipart boundary,
37*9712c20fSFrederick Mayle// but not the ending one.
38*9712c20fSFrederick Mayle- (NSData*)formDataForKey:(NSString*)key value:(NSString*)value;
39*9712c20fSFrederick Mayle- (NSData*)formDataForFileContents:(NSData*)contents name:(NSString*)name;
40*9712c20fSFrederick Mayle- (NSData*)formDataForFile:(NSString*)file name:(NSString*)name;
41*9712c20fSFrederick Mayle@end
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle@implementation HTTPMultipartUpload
44*9712c20fSFrederick Mayle//=============================================================================
45*9712c20fSFrederick Mayle#pragma mark -
46*9712c20fSFrederick Mayle#pragma mark || Private ||
47*9712c20fSFrederick Mayle//=============================================================================
48*9712c20fSFrederick Mayle- (NSString*)multipartBoundary {
49*9712c20fSFrederick Mayle  // The boundary has 27 '-' characters followed by 16 hex digits
50*9712c20fSFrederick Mayle  return [NSString
51*9712c20fSFrederick Mayle      stringWithFormat:@"---------------------------%08X%08X", rand(), rand()];
52*9712c20fSFrederick Mayle}
53*9712c20fSFrederick Mayle
54*9712c20fSFrederick Mayle//=============================================================================
55*9712c20fSFrederick Mayle- (NSData*)formDataForKey:(NSString*)key value:(NSString*)value {
56*9712c20fSFrederick Mayle  NSMutableData* data = [NSMutableData data];
57*9712c20fSFrederick Mayle  [self appendBoundaryData:data];
58*9712c20fSFrederick Mayle
59*9712c20fSFrederick Mayle  NSString* escaped = PercentEncodeNSString(key);
60*9712c20fSFrederick Mayle  NSString* fmt = @"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
61*9712c20fSFrederick Mayle  NSString *form = [NSString stringWithFormat:fmt, escaped, value];
62*9712c20fSFrederick Mayle
63*9712c20fSFrederick Mayle  [data appendData:[form dataUsingEncoding:NSUTF8StringEncoding]];
64*9712c20fSFrederick Mayle  return data;
65*9712c20fSFrederick Mayle}
66*9712c20fSFrederick Mayle
67*9712c20fSFrederick Mayle//=============================================================================
68*9712c20fSFrederick Mayle- (void)appendBoundaryData:(NSMutableData*)data {
69*9712c20fSFrederick Mayle  NSString* fmt = @"--%@\r\n";
70*9712c20fSFrederick Mayle  NSString* pre = [NSString stringWithFormat:fmt, boundary_];
71*9712c20fSFrederick Mayle
72*9712c20fSFrederick Mayle  [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
73*9712c20fSFrederick Mayle}
74*9712c20fSFrederick Mayle
75*9712c20fSFrederick Mayle//=============================================================================
76*9712c20fSFrederick Mayle#pragma mark -
77*9712c20fSFrederick Mayle#pragma mark || Public ||
78*9712c20fSFrederick Mayle//=============================================================================
79*9712c20fSFrederick Mayle- (id)initWithURL:(NSURL*)url {
80*9712c20fSFrederick Mayle  if ((self = [super initWithURL:url])) {
81*9712c20fSFrederick Mayle    boundary_ = [[self multipartBoundary] retain];
82*9712c20fSFrederick Mayle    files_ = [[NSMutableDictionary alloc] init];
83*9712c20fSFrederick Mayle  }
84*9712c20fSFrederick Mayle
85*9712c20fSFrederick Mayle  return self;
86*9712c20fSFrederick Mayle}
87*9712c20fSFrederick Mayle
88*9712c20fSFrederick Mayle//=============================================================================
89*9712c20fSFrederick Mayle- (void)dealloc {
90*9712c20fSFrederick Mayle  [parameters_ release];
91*9712c20fSFrederick Mayle  [files_ release];
92*9712c20fSFrederick Mayle  [boundary_ release];
93*9712c20fSFrederick Mayle
94*9712c20fSFrederick Mayle  [super dealloc];
95*9712c20fSFrederick Mayle}
96*9712c20fSFrederick Mayle
97*9712c20fSFrederick Mayle//=============================================================================
98*9712c20fSFrederick Mayle- (void)setParameters:(NSDictionary*)parameters {
99*9712c20fSFrederick Mayle  if (parameters != parameters_) {
100*9712c20fSFrederick Mayle    [parameters_ release];
101*9712c20fSFrederick Mayle    parameters_ = [parameters copy];
102*9712c20fSFrederick Mayle  }
103*9712c20fSFrederick Mayle}
104*9712c20fSFrederick Mayle
105*9712c20fSFrederick Mayle//=============================================================================
106*9712c20fSFrederick Mayle- (NSDictionary*)parameters {
107*9712c20fSFrederick Mayle  return parameters_;
108*9712c20fSFrederick Mayle}
109*9712c20fSFrederick Mayle
110*9712c20fSFrederick Mayle//=============================================================================
111*9712c20fSFrederick Mayle- (void)addFileAtPath:(NSString*)path name:(NSString*)name {
112*9712c20fSFrederick Mayle  [files_ setObject:path forKey:name];
113*9712c20fSFrederick Mayle}
114*9712c20fSFrederick Mayle
115*9712c20fSFrederick Mayle//=============================================================================
116*9712c20fSFrederick Mayle- (void)addFileContents:(NSData*)data name:(NSString*)name {
117*9712c20fSFrederick Mayle  [files_ setObject:data forKey:name];
118*9712c20fSFrederick Mayle}
119*9712c20fSFrederick Mayle
120*9712c20fSFrederick Mayle//=============================================================================
121*9712c20fSFrederick Mayle- (NSDictionary*)files {
122*9712c20fSFrederick Mayle  return files_;
123*9712c20fSFrederick Mayle}
124*9712c20fSFrederick Mayle
125*9712c20fSFrederick Mayle//=============================================================================
126*9712c20fSFrederick Mayle- (NSString*)HTTPMethod {
127*9712c20fSFrederick Mayle  return @"POST";
128*9712c20fSFrederick Mayle}
129*9712c20fSFrederick Mayle
130*9712c20fSFrederick Mayle//=============================================================================
131*9712c20fSFrederick Mayle- (NSString*)contentType {
132*9712c20fSFrederick Mayle  return [NSString
133*9712c20fSFrederick Mayle      stringWithFormat:@"multipart/form-data; boundary=%@", boundary_];
134*9712c20fSFrederick Mayle}
135*9712c20fSFrederick Mayle
136*9712c20fSFrederick Mayle//=============================================================================
137*9712c20fSFrederick Mayle- (NSData*)bodyData {
138*9712c20fSFrederick Mayle  NSMutableData* postBody = [NSMutableData data];
139*9712c20fSFrederick Mayle
140*9712c20fSFrederick Mayle  // Add any parameters to the message
141*9712c20fSFrederick Mayle  NSArray* parameterKeys = [parameters_ allKeys];
142*9712c20fSFrederick Mayle  NSString* key;
143*9712c20fSFrederick Mayle
144*9712c20fSFrederick Mayle  NSInteger count = [parameterKeys count];
145*9712c20fSFrederick Mayle  for (NSInteger i = 0; i < count; ++i) {
146*9712c20fSFrederick Mayle    key = [parameterKeys objectAtIndex:i];
147*9712c20fSFrederick Mayle    [postBody appendData:[self formDataForKey:key
148*9712c20fSFrederick Mayle                                        value:[parameters_ objectForKey:key]]];
149*9712c20fSFrederick Mayle  }
150*9712c20fSFrederick Mayle
151*9712c20fSFrederick Mayle  // Add any files to the message
152*9712c20fSFrederick Mayle  NSArray* fileNames = [files_ allKeys];
153*9712c20fSFrederick Mayle  for (NSString* name in fileNames) {
154*9712c20fSFrederick Mayle    // First append boundary
155*9712c20fSFrederick Mayle    [self appendBoundaryData:postBody];
156*9712c20fSFrederick Mayle    // Then the formdata
157*9712c20fSFrederick Mayle    id fileOrData = [files_ objectForKey:name];
158*9712c20fSFrederick Mayle    [HTTPRequest appendFileToBodyData:postBody
159*9712c20fSFrederick Mayle                             withName:name
160*9712c20fSFrederick Mayle                       withFileOrData:fileOrData];
161*9712c20fSFrederick Mayle  }
162*9712c20fSFrederick Mayle
163*9712c20fSFrederick Mayle  NSString* epilogue = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_];
164*9712c20fSFrederick Mayle  [postBody appendData:[epilogue dataUsingEncoding:NSUTF8StringEncoding]];
165*9712c20fSFrederick Mayle
166*9712c20fSFrederick Mayle  return postBody;
167*9712c20fSFrederick Mayle}
168*9712c20fSFrederick Mayle
169*9712c20fSFrederick Mayle@end
170