Subversion Repositories DevTools

Rev

Rev 29 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
29 jtweddle 1
<!--METADATA
2
	TYPE="TypeLib"
3
	NAME="Microsoft ActiveX Data Objects 2.5 Library"
4
	UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
5
	VERSION="2.5"
6
-->
7
<!--#INCLUDE FILE="clsField.asp"-->
8
<%
9
' ------------------------------------------------------------------------------
10
'	Author:		Lewis Moten
11
'	Email:		Lewis@Moten.com
12
'	URL:		http://www.lewismoten.com
13
'	Date:		March 19, 2002
14
' ------------------------------------------------------------------------------
15
 
16
' Upload class retrieves multi-part form data posted to web page
17
' and parses it into objects that are easy to interface with.
18
' Requires MDAC (ADODB) COM components found on most servers today
19
' Additional compenents are not necessary.
20
'
21
' Demo:
22
'	Set objUpload = new clsUpload
23
'		Initializes object and parses all posted multi-part from data.
24
'		Once this as been done, Access to the Request object is restricted
25
'
26
'	objUpload.Count
27
'		Number of fields retrieved
28
'
29
'		use: Response.Write "There are " & objUpload.Count & " fields."
30
'
31
'	objUpload.Fields
32
'		Access to field objects.  This is the default propert so it does
33
'		not necessarily have to be specified.  You can also determine if
34
'		you wish to specify the field index, or the field name.
35
'
36
'		Use:
37
'			Set objField = objUpload.Fields("File1")
38
'			Set objField = objUpload("File1")
39
'			Set objField = objUpload.Fields(0)
40
'			Set objField = objUpload(0)
41
'			Response.Write objUpload("File1").Name
42
'			Response.Write objUpload(0).Name
43
'
44
' ------------------------------------------------------------------------------
45
'
46
' List of all fields passed:
47
'
48
'	For i = 0 To objUpload.Count - 1
49
'		Response.Write objUpload(i).Name & "<BR>"
50
'	Next
51
'
52
' ------------------------------------------------------------------------------
53
'
54
' HTML needed to post multipart/form-data
55
'
56
'<FORM method="post" encType="multipart/form-data" action="Upload.asp">
57
'	<INPUT type="File" name="File1">
58
'	<INPUT type="Submit" value="Upload">
59
'</FORM>
60
 
61
Class clsUpload
62
' ------------------------------------------------------------------------------
63
 
64
	Private mbinData			' bytes visitor sent to server
65
	Private mlngChunkIndex		' byte where next chunk starts
66
	Private mlngBytesReceived	' length of data
67
	Private mstrDelimiter		' Delimiter between multipart/form-data (43 chars)
68
 
69
	Private CR					' ANSI Carriage Return
70
	Private LF					' ANSI Line Feed
71
	Private CRLF				' ANSI Carriage Return & Line Feed
72
 
73
	Private mobjFieldAry()		' Array to hold field objects
74
	Private mlngCount			' Number of fields parsed
75
 
76
' ------------------------------------------------------------------------------
77
	Private Sub RequestData
78
 
79
		Dim llngLength		' Number of bytes received
80
 
81
		' Determine number bytes visitor sent
82
		mlngBytesReceived = Request.TotalBytes
83
 
84
		' Store bytes recieved from visitor
85
		mbinData = Request.BinaryRead(mlngBytesReceived)
86
 
87
	End Sub
88
' ------------------------------------------------------------------------------
89
	Private Sub ParseDelimiter()
90
 
91
		' Delimiter seperates multiple pieces of form data
92
			' "around" 43 characters in length
93
			' next character afterwards is carriage return (except last line has two --)
94
			' first part of delmiter is dashes followed by hex number
95
			' hex number is possibly the browsers session id?
96
 
97
		' Examples:
98
 
99
		' -----------------------------7d230d1f940246
100
		' -----------------------------7d22ee291ae0114
101
 
102
		mstrDelimiter = MidB(mbinData, 1, InStrB(1, mbinData, CRLF) - 1)
103
 
104
	End Sub
105
' ------------------------------------------------------------------------------
106
	Private Sub ParseData()
107
 
108
		' This procedure loops through each section (chunk) found within the
109
		' delimiters and sends them to the parse chunk routine
110
 
111
		Dim llngStart	' start position of chunk data
112
		Dim llngLength	' Length of chunk
113
		Dim llngEnd		' Last position of chunk data
114
		Dim lbinChunk	' Binary contents of chunk
115
 
116
		' Initialize at first character
117
		llngStart = 1
118
 
119
		' Find start position
120
		llngStart = InStrB(llngStart, mbinData, mstrDelimiter & CRLF)
121
 
122
		' While the start posotion was found
123
		While Not llngStart = 0
124
 
125
			' Find the end position (after the start position)
126
			llngEnd = InStrB(llngStart + 1, mbinData, mstrDelimiter) - 2
127
 
128
			' Determine Length of chunk
129
			llngLength = llngEnd - llngStart
130
 
131
			' Pull out the chunk
132
			lbinChunk = MidB(mbinData, llngStart, llngLength)
133
 
134
			' Parse the chunk
135
			Call ParseChunk(lbinChunk)
136
 
137
			' Look for next chunk after the start position
138
			llngStart = InStrB(llngStart + 1, mbinData, mstrDelimiter & CRLF)
139
 
140
		Wend
141
 
142
	End Sub
143
' ------------------------------------------------------------------------------
144
	Private Sub ParseChunk(ByRef pbinChunk)
145
 
146
		' This procedure gets a chunk passed to it and parses its contents.
147
		' There is a general format that the chunk follows.
148
 
149
		' First, the deliminator appears
150
 
151
		' Next, headers are listed on each line that define properties of the chunk.
152
 
153
		'	Content-Disposition: form-data: name="File1"; filename="C:\Photo.gif"
154
		'	Content-Type: image/gif
155
 
156
		' After this, a blank line appears and is followed by the binary data.
157
 
158
		Dim lstrName			' Name of field
159
		Dim lstrFileName		' File name of binary data
160
		Dim lstrContentType		' Content type of binary data
161
		Dim lbinData			' Binary data
162
		Dim lstrDisposition		' Content Disposition
163
		Dim lstrValue			' Value of field
164
 
165
		' Parse out the content dispostion
166
		lstrDisposition = ParseDisposition(pbinChunk)
167
 
168
			' And Parse the Name
169
			lstrName = ParseName(lstrDisposition)
170
 
171
			' And the file name
172
			lstrFileName = ParseFileName(lstrDisposition)
173
 
174
		' Parse out the Content Type
175
		lstrContentType = ParseContentType(pbinChunk)
176
 
177
		' If the content type is not defined, then assume the
178
		' field is a normal form field
179
		If lstrContentType = "" Then
180
 
181
			' Parse Binary Data as Unicode
182
			lstrValue = CStrU(ParseBinaryData(pbinChunk))
183
 
184
		' Else assume the field is binary data
185
		Else
186
 
187
			' Parse Binary Data
188
			lbinData = ParseBinaryData(pbinChunk)
189
 
190
		End If
191
 
192
		' Add a new field
193
		Call AddField(lstrName, lstrFileName, lstrContentType, lstrValue, lbinData)
194
 
195
	End Sub
196
' ------------------------------------------------------------------------------
197
	Private Sub AddField(ByRef pstrName, ByRef pstrFileName, ByRef pstrContentType, ByRef pstrValue, ByRef pbinData)
198
 
199
		Dim lobjField		' Field object class
200
 
201
		' Add a new index to the field array
202
		' Make certain not to destroy current fields
203
		ReDim Preserve mobjFieldAry(mlngCount)
204
 
205
		' Create new field object
206
		Set lobjField = New clsField
207
 
208
		' Set field properties
209
		lobjField.Name = pstrName
210
		lobjField.FilePath = pstrFileName				
211
		lobjField.ContentType = pstrContentType
212
 
213
		' If field is not a binary file
214
		If LenB(pbinData) = 0 Then
215
 
216
			lobjField.BinaryData = ChrB(0)
217
			lobjField.Value = pstrValue
218
			lobjField.Length = Len(pstrValue)
219
 
220
		' Else field is a binary file
221
		Else
222
 
223
			lobjField.BinaryData = pbinData
224
			lobjField.Length = LenB(pbinData)
225
			lobjField.Value = ""
226
 
227
		End If
228
 
229
		' Set field array index to new field
230
		Set mobjFieldAry(mlngCount) = lobjField
231
 
232
		' Incriment field count
233
		mlngCount = mlngCount + 1
234
 
235
	End Sub
236
' ------------------------------------------------------------------------------
237
	Private Function ParseBinaryData(ByRef pbinChunk)
238
 
239
		' Parses binary content of the chunk
240
 
241
		Dim llngStart	' Start Position
242
 
243
		' Find first occurence of a blank line
244
		llngStart = InStrB(1, pbinChunk, CRLF & CRLF)
245
 
246
		' If it doesn't exist, then return nothing
247
		If llngStart = 0 Then Exit Function
248
 
249
		' Incriment start to pass carriage returns and line feeds
250
		llngStart = llngStart + 4
251
 
252
		' Return the last part of the chunk after the start position
253
		ParseBinaryData = MidB(pbinChunk, llngStart)
254
 
255
	End Function
256
' ------------------------------------------------------------------------------
257
	Private Function ParseContentType(ByRef pbinChunk)
258
 
259
		' Parses the content type of a binary file.
260
		'	example: image/gif is the content type of a GIF image.
261
 
262
		Dim llngStart	' Start Position
263
		Dim llngEnd		' End Position
264
		Dim llngLength	' Length
265
 
266
		' Fid the first occurance of a line starting with Content-Type:
267
		llngStart = InStrB(1, pbinChunk, CRLF & CStrB("Content-Type:"), vbTextCompare)
268
 
269
		' If not found, return nothing
270
		If llngStart = 0 Then Exit Function
271
 
272
		' Find the end of the line
273
		llngEnd = InStrB(llngStart + 15, pbinChunk, CR)
274
 
275
		' If not found, return nothing
276
		If llngEnd = 0 Then Exit Function
277
 
278
		' Adjust start position to start after the text "Content-Type:"
279
		llngStart = llngStart + 15
280
 
281
		' If the start position is the same or past the end, return nothing
282
		If llngStart >= llngEnd Then Exit Function
283
 
284
		' Determine length
285
		llngLength = llngEnd - llngStart
286
 
287
		' Pull out content type
288
		' Convert to unicode
289
		' Trim out whitespace
290
		' Return results
291
		ParseContentType = Trim(CStrU(MidB(pbinChunk, llngStart, llngLength)))
292
 
293
	End Function
294
' ------------------------------------------------------------------------------
295
	Private Function ParseDisposition(ByRef pbinChunk)
296
 
297
		' Parses the content-disposition from a chunk of data
298
		'
299
		' Example:
300
		'
301
		'	Content-Disposition: form-data: name="File1"; filename="C:\Photo.gif"
302
		'
303
		'	Would Return:
304
		'		form-data: name="File1"; filename="C:\Photo.gif"
305
 
306
		Dim llngStart	' Start Position
307
		Dim llngEnd		' End Position
308
		Dim llngLength	' Length
309
 
310
		' Find first occurance of a line starting with Content-Disposition:
311
		llngStart = InStrB(1, pbinChunk, CRLF & CStrB("Content-Disposition:"), vbTextCompare)
312
 
313
		' If not found, return nothing
314
		If llngStart = 0 Then Exit Function
315
 
316
		' Find the end of the line
317
		llngEnd = InStrB(llngStart + 22, pbinChunk, CRLF)
318
 
319
		' If not found, return nothing
320
		If llngEnd = 0 Then Exit Function
321
 
322
		' Adjust start position to start after the text "Content-Disposition:"
323
		llngStart = llngStart + 22
324
 
325
		' If the start position is the same or past the end, return nothing
326
		If llngStart >= llngEnd Then Exit Function
327
 
328
		' Determine Length
329
		llngLength = llngEnd - llngStart
330
 
331
		' Pull out content disposition
332
		' Convert to Unicode
333
		' Return Results
334
		ParseDisposition = CStrU(MidB(pbinChunk, llngStart, llngLength))
335
 
336
	End Function
337
' ------------------------------------------------------------------------------
338
	Private Function ParseName(ByRef pstrDisposition)
339
 
340
		' Parses the name of the field from the content disposition
341
		'
342
		' Example
343
		'
344
		'	form-data: name="File1"; filename="C:\Photo.gif"
345
		'
346
		'	Would Return:
347
		'		File1
348
 
349
		Dim llngStart	' Start Position
350
		Dim llngEnd		' End Position
351
		Dim llngLength	' Length
352
 
353
		' Find first occurance of text name="
354
		llngStart = InStr(1, pstrDisposition, "name=""", vbTextCompare)
355
 
356
		' If not found, return nothing
357
		If llngStart = 0 Then Exit Function
358
 
359
		' Find the closing quote
360
		llngEnd = InStr(llngStart + 6, pstrDisposition, """")
361
 
362
		' If not found, return nothing
363
		If llngEnd = 0 Then Exit Function
364
 
365
		' Adjust start position to start after the text name="
366
		llngStart = llngStart + 6
367
 
368
		' If the start position is the same or past the end, return nothing
369
		If llngStart >= llngEnd Then Exit Function
370
 
371
		' Determine Length
372
		llngLength = llngEnd - llngStart
373
 
374
		' Pull out field name
375
		' Return results
376
		ParseName = Mid(pstrDisposition, llngStart, llngLength)
377
 
378
	End Function
379
' ------------------------------------------------------------------------------
380
	Private Function ParseFileName(ByRef pstrDisposition)
381
		' Parses the name of the field from the content disposition
382
		'
383
		' Example
384
		'
385
		'	form-data: name="File1"; filename="C:\Photo.gif"
386
		'
387
		'	Would Return:
388
		'		C:\Photo.gif
389
 
390
		Dim llngStart	' Start Position
391
		Dim llngEnd		' End Position
392
		Dim llngLength	' Length
393
 
394
		' Find first occurance of text filename="
395
		llngStart = InStr(1, pstrDisposition, "filename=""", vbTextCompare)
396
 
397
		' If not found, return nothing
398
		If llngStart = 0 Then Exit Function
399
 
400
		' Find the closing quote
401
		llngEnd = InStr(llngStart + 10, pstrDisposition, """")
402
 
403
		' If not found, return nothing
404
		If llngEnd = 0 Then Exit Function
405
 
406
		' Adjust start position to start after the text filename="
407
		llngStart = llngStart + 10
408
 
409
		' If the start position is the same of past the end, return nothing
410
		If llngStart >= llngEnd Then Exit Function
411
 
412
		' Determine length
413
		llngLength = llngEnd - llngStart
414
 
415
		' Pull out file name
416
		' Return results
417
		ParseFileName = Mid(pstrDisposition, llngStart, llngLength)
418
 
419
	End Function
420
' ------------------------------------------------------------------------------
421
	Public Property Get Count()
422
 
423
		' Return number of fields found
424
		Count = mlngCount
425
 
426
	End Property
427
' ------------------------------------------------------------------------------
428
 
429
	Public Default Property Get Fields(ByVal pstrName)
430
 
431
		Dim llngIndex	' Index of current field
432
 
433
		' If a number was passed
434
		If IsNumeric(pstrName) Then
435
 
436
			llngIndex = CLng(pstrName)
437
 
438
			' If programmer requested an invalid number
439
			If llngIndex > mlngCount - 1 Or llngIndex < 0 Then
440
				' Raise an error
441
				Call Err.Raise(vbObjectError + 1, "clsUpload.asp", "Object does not exist within the ordinal reference.")
442
				Exit Property
443
			End If
444
 
445
			' Return the field class for the index specified
446
			Set Fields = mobjFieldAry(pstrName)
447
 
448
		' Else a field name was passed
449
		Else
450
 
451
			' convert name to lowercase
452
			pstrName = LCase(pstrname)
453
 
454
			' Loop through each field
455
			For llngIndex = 0 To mlngCount - 1
456
 
457
				' If name matches current fields name in lowercase
458
				If LCase(mobjFieldAry(llngIndex).Name) = pstrName Then
459
 
460
					' Return Field Class
461
					Set Fields = mobjFieldAry(llngIndex)
462
					Exit Property
463
 
464
				End If
465
 
466
			Next
467
 
468
		End If
469
 
470
		' If matches were not found, return an empty field
471
		Set Fields = New clsField
472
 
473
'		' ERROR ON NonExistant:
474
'		' If matches were not found, raise an error of a non-existent field
475
'		Call Err.Raise(vbObjectError + 1, "clsUpload.asp", "Object does not exist within the ordinal reference.")
476
'		Exit Property
477
 
478
	End Property
479
' ------------------------------------------------------------------------------
480
	Private Sub Class_Terminate()
481
 
482
		' This event is called when you destroy the class.
483
		'
484
		' Example:
485
		'	Set objUpload = Nothing
486
		'
487
		' Example:
488
		'	Response.End
489
		'
490
		' Example:
491
		'	Page finnishes executing ...
492
 
493
		Dim llngIndex	' Current Field Index
494
 
495
		' Loop through fields
496
		For llngIndex = 0 To mlngCount - 1
497
 
498
			' Release field object
499
			Set mobjFieldAry(llngIndex) = Nothing
500
 
501
		Next
502
 
503
		' Redimension array and remove all data within
504
		ReDim mobjFieldAry(-1)
505
 
506
	End Sub
507
' ------------------------------------------------------------------------------
508
	Private Sub Class_Initialize()
509
 
510
		' This event is called when you instantiate the class.
511
		'
512
		' Example:
513
		'	Set objUpload = New clsUpload
514
 
515
		' Redimension array with nothing
516
		ReDim mobjFieldAry(-1)
517
 
518
		' Compile ANSI equivilants of carriage returns and line feeds
519
 
520
		CR = ChrB(Asc(vbCr))	' vbCr		Carriage Return
521
		LF = ChrB(Asc(vbLf))	' vbLf		Line Feed
522
		CRLF = CR & LF			' vbCrLf	Carriage Return & Line Feed
523
 
524
		' Set field count to zero
525
		mlngCount = 0
526
 
527
		' Request data
528
		Call RequestData
529
 
530
		' Parse out the delimiter
531
		Call ParseDelimiter()
532
 
533
		' Parse the data
534
		Call ParseData
535
 
536
	End Sub
537
' ------------------------------------------------------------------------------
538
	Private Function CStrU(ByRef pstrANSI)
539
 
540
		' Converts an ANSI string to Unicode
541
		' Best used for small strings
542
 
543
		Dim llngLength	' Length of ANSI string
544
		Dim llngIndex	' Current position
545
 
546
		' determine length
547
		llngLength = LenB(pstrANSI)
548
 
549
		' Loop through each character
550
		For llngIndex = 1 To llngLength
551
 
552
			' Pull out ANSI character
553
			' Get Ascii value of ANSI character
554
			' Get Unicode Character from Ascii
555
			' Append character to results
556
			CStrU = CStrU & Chr(AscB(MidB(pstrANSI, llngIndex, 1)))
557
 
558
		Next
559
 
560
	End Function
561
' ------------------------------------------------------------------------------
562
	Private Function CStrB(ByRef pstrUnicode)
563
 
564
		' Converts a Unicode string to ANSI
565
		' Best used for small strings
566
 
567
		Dim llngLength	' Length of ANSI string
568
		Dim llngIndex	' Current position
569
 
570
		' determine length
571
		llngLength = Len(pstrUnicode)
572
 
573
		' Loop through each character
574
		For llngIndex = 1 To llngLength
575
 
576
			' Pull out Unicode character
577
			' Get Ascii value of Unicode character
578
			' Get ANSI Character from Ascii
579
			' Append character to results
580
			CStrB = CStrB & ChrB(Asc(Mid(pstrUnicode, llngIndex, 1)))
581
 
582
		Next
583
 
584
	End Function
585
' ------------------------------------------------------------------------------
586
End Class
587
' ------------------------------------------------------------------------------
588
%>