Form Upload of JPEG files to be used in photo album

J

Jason_Joe

I am new to web design so please go gentle on me (ie assume I am really
dumb).

I want to create a site which allows guests to upload their photo's (so
mainly JPEG) file of a maximum size and save it in a specific directory on
my site's host directory.

I know that it is possible but don't know where to start and am sure that
this very thing has been done many times before so am hoping that rather
than me spending 2 weeks reading up on the method someone who has done this
before code post the code which they used and explain what each line does.

p.s. I do not simply want someone to tell me to use a full photo album
script (such as FotoFrame) as what I want is very simple and I want to learn
as I work through the problem myself (with your help) rather than have a zip
file which I extract....

Thanks

Jason_Joe
 
C

Cameron

Jason_Joe said:
I am new to web design so please go gentle on me (ie assume I am really
dumb).

Then you aren't going to like this next part.
I want to create a site which allows guests to upload their photo's (so
mainly JPEG) file of a maximum size and save it in a specific directory on
my site's host directory.

You will need a server side scripting language for this, Perl, PHP, ASP
etc...
I know that it is possible but don't know where to start and am sure that
this very thing has been done many times before so am hoping that rather
than me spending 2 weeks reading up on the method someone who has done this
before code post the code which they used and explain what each line does.

*Nods* some one may do, and indeed it has been done many times before,
however helping a newbie become good with scripting languages isn't a
small task, and your request is lacking in content, what works on one
"host" may not work on another, maybe tell us what your host's server
supports for scripting languages (Mentioned above).
p.s. I do not simply want someone to tell me to use a full photo album
script (such as FotoFrame) as what I want is very simple and I want to learn
as I work through the problem myself (with your help) rather than have a zip
file which I extract....

Thanks

Jason_Joe

Finally, may I suggest that you take this to one of the scripting
languages newsgroups once you have figured out which ones you can use
(if it's a free host then chances are not many)

And may I also suggest that you have a look on google for this, there
are bound to be hundreds of matches.

~Cameron
 
C

Chris Leonard

Hi.

Like Cameron said, you'll need a server side scripting language like ASP.
Here is some ASP code which I used - the class file is not mine I found it
on the web somewhere - See if you can make use of this. I know it works on
Brinkster.com which is a free ASP host (before anyone says it they are not
the only free host and they are not the best either)

Hope this helps you.

Chris

ASP Script:
<!--#INCLUDE FILE="upload.class"-->
<%
Dim oUpload
Dim oFile
Dim sFileName
Dim oFSO
Dim sPath
Dim sNewData
Dim nLength
Dim bytBinaryData
Dim sReadLine

Const nForReading = 1
Const nForWriting = 2
Const nForAppending = 8
Const nSetLength = 55000

' grab the uploaded file data
Set oUpload = New clsUpload
Set oFile = oUpload("File1")

set oField = new clsField

sFileName = oFile.FileName
If Not InStr(sFileName, "\") = 0 Then
sFileName = Mid(sFileName, InStrRev(sFileName, "\") + 1)
End If

'Get the file extention
extn = mid(sFileName,instr(1,sFileName,"."),4)

' Convert the binary data to Ascii
bytBinaryData = oFile.BinaryData
nLength = LenB(bytBinaryData)

if nLength > nSetLength then
Response.Write "Sorry, upload file size must not exceed 50Kb"
else
For nIndex = 1 To nLength -1
sNewData = sNewData & Chr(AscB(MidB(bytBinaryData, nIndex, 1)))
Next

' Save the file to the file system
sPath = Server.MapPath("\") & "\pics\"

'Get the id value of our record
sID = oUpload("id").Value
sPictureName = (DateDiff("s", "1/1/2000", now())) & extn

'Write the picture out to the pic folder
Set oFSO = Server.CreateObject("Scripting.FileSystemObject")
oFSO.OpenTextFile(sPath & sPictureName, nForWriting, True).Write sNewData
Set oFSO = Nothing
Set oFile = Nothing
Set oUpload = Nothing

'Open the database
set MyConnection = server.createobject("ADODB.Connection")
'MyConnection.Open "DRIVER={Microsoft Access Driver (*.mdb)};" & "DBQ=" &
Server.Mappath("\amber.mdb")
MyConnection.Open "DRIVER={Microsoft Access Driver (*.mdb)};" & "DBQ=" &
Server.Mappath("db\amber.mdb")

SQLQuery = "delete from GuestPic where id = '" & sID & "'"
set rtnval = MyConnection.Execute(SQLQuery)

'Insert new picture record
SQLQuery = "insert into GuestPic "
SQLQuery = SQLQuery & "(id, PicName) "
SQLQuery = SQLQuery & "values ('" & sID & "','" & sPictureName & "')"

set rtnval = MyConnection.Execute(SQLQuery)
MyConnection.Close

end if
%>
<HTML>
<HEAD><TITLE>Picture Upload</TITLE>
<BODY>
<P>
File uploaded
<P>
</body>
</html>


Class file:
<%
' --------------------------------------------------------------------------
----
' Container of Field Properties
Class clsField
Public FileName
Public ContentType
Public Value
Public FieldName
Public Length
Public BinaryData
End Class
' --------------------------------------------------------------------------
----
Class clsUpload
' --------------------------------------------------------------------------
----
Private nFieldCount
Private oFields()

' --------------------------------------------------------------------------
----
Public Property Get Count()
Count = nFieldCount
End Property
' --------------------------------------------------------------------------
----
Public Default Property Get Field(ByRef asFieldName)
Dim lnLength
Dim lnIndex

lnLength = UBound(oFields)

If IsNumeric(asFieldName) Then
If lnLength >= asFieldName And asFieldName > -1 Then
Set Field = oFields(asFieldName)
Else
Set Field = New clsField
End If
Else
For lnIndex = 0 To lnLength
If LCase(oFields(lnIndex).FieldName) = LCase(asFieldName) Then
Set Field = oFields(lnIndex)
Exit Property
End If
Next
Set Field = New clsField
End If
End Property
' --------------------------------------------------------------------------
----
Public Function Exists(ByRef avKeyIndex)
Exists = Not IndexOf(avKeyIndex) = -1
End Function
' --------------------------------------------------------------------------
----
Public Property Get ValueOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
ValueOf = oFields(lnIndex).Value
End Property
' --------------------------------------------------------------------------
----
Public Property Get FileNameOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
FileNameOf = oFields(lnIndex).FileName
End Property
' --------------------------------------------------------------------------
----
Public Property Get LengthOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
LengthOf = oFields(lnIndex).LengthOf
End Property
' --------------------------------------------------------------------------
----
Public Property Get BinaryDataOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
BinaryDataOf = oFields(lnIndex).BinaryData
End Property
' --------------------------------------------------------------------------
----
Private Function IndexOf(ByVal avKeyIndex)
Dim lnIndex
If IsNumeric(asFieldName) Then
avKeyIndex = CLng(avKeyIndex)
If nFieldCount > avKeyIndex And avKeyIndex > -1 Then
IndexOf = avKeyIndex
Else
IndexOf = -1
End If
Else
For lnIndex = 0 To nFieldCount - 1
If LCase(oFields(lnIndex).FieldName) = LCase(avKeyIndex) Then
IndexOf = lnIndex
Exit Function
End If
Next
IndexOf = -1
End If
End Function
' --------------------------------------------------------------------------
----
Public Property Get ContentTypeOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
ContentTypeOf = oFields(lnIndex).ContentType
End Property
' --------------------------------------------------------------------------
----
Private Sub Class_Terminate()
For lnIndex = 0 To nFieldCount - 1
Set oFields(0) = Nothing
Next
End Sub
' --------------------------------------------------------------------------
----
Private Sub Class_Initialize()

Dim lnBytes ' Bytes received from the client
Dim lnByteCount ' Number of bytes received
Dim lnStartPosition ' Position at which content begins
Dim lnEndPosition ' Position at which content ends

Dim loDic ' Contains properties of each
' specific field
' Local dictionary object(s)
' to be appended to class-scope
' dictioary object.

Dim lnBoundaryBytes ' Bytes contained within the current boundary
Dim lnBoundaryStart ' Position at wich the current boundary begins
' within the lnBytes binary data.
Dim lnBoundaryEnd ' Position at wich the current boundary ends
' within the lnBytes binary data.
Dim lnDispositionPosition

Dim lsFieldName ' Name of the current field being parsed from
' Binary Data
Dim lsFileName ' Name of the file within the current boundary
Dim lnFileNamePosition ' Location of file name within current boundary

' Initialize Fields
nFieldCount = 0
ReDim oFields(-1)

' Read the bytes (binary data) into memory
lnByteCount = Request.TotalBytes
lnBytes = Request.BinaryRead(lnByteCount)

'Get the lnBoundaryBytes
lnStartPosition = 1
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(vbCr))

lnBoundaryBytes = MidB(lnBytes, lnStartPosition, lnEndPosition -
lnStartPosition)

lnBoundaryStart = InstrB(1, lnBytes, lnBoundaryBytes)


' Loop until the BoundaryBytes begin with "--"
Do Until (lnBoundaryStart = InstrB(lnBytes, lnBoundaryBytes &
CStrB("--")))

' All data within this boundary is stored within a local dictionary
' to be appended to the class-scope dictionary.

ReDim Preserve oFields(nFieldCount)
nFieldCount = nFieldCount + 1

Set loField = New clsField

lnDispositionPosition = InstrB(lnBoundaryStart, lnBytes,
CStrB("Content-Disposition"))

' Get an object name
lnStartPosition = InstrB(lnDispositionPosition, lnBytes, CStrB("name="))
+ 6
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(""""))
lsFieldName = CStrU(MidB(lnBytes, lnStartPosition, lnEndPosition -
lnStartPosition))
loField.FieldName = lsFieldName

' Get the location fo the file name.
lnFileNamePosition = InstrB(lnBoundaryStart, lnBytes, CStrB("filename="))
lnBoundaryEnd = InstrB(lnEndPosition, lnBytes, lnBoundaryBytes)

'Test if object is a file
If Not lnFileNamePosition = 0 And lnFileNamePosition < lnBoundaryEnd Then

' Parse Filename
lnStartPosition = lnFileNamePosition + 10
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(""""))
lsFileName =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.FileName = lsFileName

' Parse Content-Type
lnStartPosition = InstrB(lnEndPosition,lnBytes,CStrB("Content-Type:")) +
14
lnEndPosition = InstrB(lnStartPosition,lnBytes,CStrB(vbCr))
ContentType =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.ContentType = ContentType

' Parse Content
lnStartPosition = lnEndPosition + 4
lnEndPosition = InstrB(lnStartPosition,lnBytes,lnBoundaryBytes)-2
Value = MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition)
loField.BinaryData = Value & CStrB(vbNull)
loField.Length = LenB(Value)
Else

' Parse Content
lnStartPosition = InstrB(lnDispositionPosition, lnBytes, CStrB(vbCr)) +
4
lnEndPosition = InstrB(lnStartPosition, lnBytes, lnBoundaryBytes) - 2
Value =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.Value = Value
loField.Length = Len(Value)
End If

Set oFields(UBound(oFields)) = loField

'Loop to next object
lnBoundaryStart = InstrB(lnBoundaryStart + LenB(lnBoundaryBytes),
lnBytes, lnBoundaryBytes)

Set loField = Nothing

Loop

End Sub
' --------------------------------------------------------------------------
----
Private Function CStrU(ByRef psByteString)
Dim lnLength
Dim lnPosition
lnLength = LenB(psByteString)
For lnPosition = 1 To lnLength
CStrU = CStrU & Chr(AscB(MidB(psByteString, lnPosition, 1)))
Next
End Function
' --------------------------------------------------------------------------
----
Private Function CStrB(ByRef psUnicodeString)
Dim lnLength
Dim lnPosition
lnLength = Len(psUnicodeString)
For lnPosition = 1 To lnLength
CStrB = CStrB & ChrB(AscB(Mid(psUnicodeString, lnPosition, 1)))
Next
End Function
' --------------------------------------------------------------------------
 
J

Jeff Thies

Like Cameron said, you'll need a server side scripting language like ASP.
Here is some ASP code which I used - the class file is not mine I found it
on the web somewhere - See if you can make use of this. I know it works on
Brinkster.com which is a free ASP host (before anyone says it they are not
the only free host and they are not the best either)


Holy cats, VBScript is the wordiest language!

Perl:

use CGI;
my $q=new CGI;
my $image=$q->param('image');

open(IF,">path_to_directory$image") or die "$!";
while (read($image,$Buffer,1024)){print IF $Buffer}
close (IF) or die "$!";
undef $Buffer;

And that works for *any* size image, that VBScript will slooooow down for a
large file.

Pick a server language and ask in that group.

Jeff

Hope this helps you.

Chris

ASP Script:
<!--#INCLUDE FILE="upload.class"-->
<%
Dim oUpload
Dim oFile
Dim sFileName
Dim oFSO
Dim sPath
Dim sNewData
Dim nLength
Dim bytBinaryData
Dim sReadLine

Const nForReading = 1
Const nForWriting = 2
Const nForAppending = 8
Const nSetLength = 55000

' grab the uploaded file data
Set oUpload = New clsUpload
Set oFile = oUpload("File1")

set oField = new clsField

sFileName = oFile.FileName
If Not InStr(sFileName, "\") = 0 Then
sFileName = Mid(sFileName, InStrRev(sFileName, "\") + 1)
End If

'Get the file extention
extn = mid(sFileName,instr(1,sFileName,"."),4)

' Convert the binary data to Ascii
bytBinaryData = oFile.BinaryData
nLength = LenB(bytBinaryData)

if nLength > nSetLength then
Response.Write "Sorry, upload file size must not exceed 50Kb"
else
For nIndex = 1 To nLength -1
sNewData = sNewData & Chr(AscB(MidB(bytBinaryData, nIndex, 1)))
Next

' Save the file to the file system
sPath = Server.MapPath("\") & "\pics\"

'Get the id value of our record
sID = oUpload("id").Value
sPictureName = (DateDiff("s", "1/1/2000", now())) & extn

'Write the picture out to the pic folder
Set oFSO = Server.CreateObject("Scripting.FileSystemObject")
oFSO.OpenTextFile(sPath & sPictureName, nForWriting, True).Write sNewData
Set oFSO = Nothing
Set oFile = Nothing
Set oUpload = Nothing

'Open the database
set MyConnection = server.createobject("ADODB.Connection")
'MyConnection.Open "DRIVER={Microsoft Access Driver (*.mdb)};" & "DBQ=" &
Server.Mappath("\amber.mdb")
MyConnection.Open "DRIVER={Microsoft Access Driver (*.mdb)};" & "DBQ=" &
Server.Mappath("db\amber.mdb")

SQLQuery = "delete from GuestPic where id = '" & sID & "'"
set rtnval = MyConnection.Execute(SQLQuery)

'Insert new picture record
SQLQuery = "insert into GuestPic "
SQLQuery = SQLQuery & "(id, PicName) "
SQLQuery = SQLQuery & "values ('" & sID & "','" & sPictureName & "')"

set rtnval = MyConnection.Execute(SQLQuery)
MyConnection.Close

end if
%>
<HTML>
<HEAD><TITLE>Picture Upload</TITLE>
<BODY>
<P>
File uploaded
<P>
</body>
</html>


Class file:
<%
' --------------------------------------------------------------------------
----
' Container of Field Properties
Class clsField
Public FileName
Public ContentType
Public Value
Public FieldName
Public Length
Public BinaryData
End Class
' --------------------------------------------------------------------------' --------------------------------------------------------------------------' --------------------------------------------------------------------------' --------------------------------------------------------------------------
----
Public Default Property Get Field(ByRef asFieldName)
Dim lnLength
Dim lnIndex

lnLength = UBound(oFields)

If IsNumeric(asFieldName) Then
If lnLength >= asFieldName And asFieldName > -1 Then
Set Field = oFields(asFieldName)
Else
Set Field = New clsField
End If
Else
For lnIndex = 0 To lnLength
If LCase(oFields(lnIndex).FieldName) = LCase(asFieldName) Then
Set Field = oFields(lnIndex)
Exit Property
End If
Next
Set Field = New clsField
End If
End Property
' --------------------------------------------------------------------------' --------------------------------------------------------------------------
----
Public Property Get ValueOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
ValueOf = oFields(lnIndex).Value
End Property
' --------------------------------------------------------------------------
----
Public Property Get FileNameOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
FileNameOf = oFields(lnIndex).FileName
End Property
' --------------------------------------------------------------------------
----
Public Property Get LengthOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
LengthOf = oFields(lnIndex).LengthOf
End Property
' --------------------------------------------------------------------------
----
Public Property Get BinaryDataOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
BinaryDataOf = oFields(lnIndex).BinaryData
End Property
' --------------------------------------------------------------------------
----
Private Function IndexOf(ByVal avKeyIndex)
Dim lnIndex
If IsNumeric(asFieldName) Then
avKeyIndex = CLng(avKeyIndex)
If nFieldCount > avKeyIndex And avKeyIndex > -1 Then
IndexOf = avKeyIndex
Else
IndexOf = -1
End If
Else
For lnIndex = 0 To nFieldCount - 1
If LCase(oFields(lnIndex).FieldName) = LCase(avKeyIndex) Then
IndexOf = lnIndex
Exit Function
End If
Next
IndexOf = -1
End If
End Function
' --------------------------------------------------------------------------
----
Public Property Get ContentTypeOf(ByRef avKeyIndex)
Dim lnIndex
lnIndex = IndexOf(avKeyIndex)
if lnIndex = -1 Then Exit Property
ContentTypeOf = oFields(lnIndex).ContentType
End Property
' --------------------------------------------------------------------------
----
Private Sub Class_Terminate()
For lnIndex = 0 To nFieldCount - 1
Set oFields(0) = Nothing
Next
End Sub
' --------------------------------------------------------------------------
----
Private Sub Class_Initialize()

Dim lnBytes ' Bytes received from the client
Dim lnByteCount ' Number of bytes received
Dim lnStartPosition ' Position at which content begins
Dim lnEndPosition ' Position at which content ends

Dim loDic ' Contains properties of each
' specific field
' Local dictionary object(s)
' to be appended to class-scope
' dictioary object.

Dim lnBoundaryBytes ' Bytes contained within the current boundary
Dim lnBoundaryStart ' Position at wich the current boundary begins
' within the lnBytes binary data.
Dim lnBoundaryEnd ' Position at wich the current boundary ends
' within the lnBytes binary data.
Dim lnDispositionPosition

Dim lsFieldName ' Name of the current field being parsed from
' Binary Data
Dim lsFileName ' Name of the file within the current boundary
Dim lnFileNamePosition ' Location of file name within current boundary

' Initialize Fields
nFieldCount = 0
ReDim oFields(-1)

' Read the bytes (binary data) into memory
lnByteCount = Request.TotalBytes
lnBytes = Request.BinaryRead(lnByteCount)

'Get the lnBoundaryBytes
lnStartPosition = 1
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(vbCr))

lnBoundaryBytes = MidB(lnBytes, lnStartPosition, lnEndPosition -
lnStartPosition)

lnBoundaryStart = InstrB(1, lnBytes, lnBoundaryBytes)


' Loop until the BoundaryBytes begin with "--"
Do Until (lnBoundaryStart = InstrB(lnBytes, lnBoundaryBytes &
CStrB("--")))

' All data within this boundary is stored within a local dictionary
' to be appended to the class-scope dictionary.

ReDim Preserve oFields(nFieldCount)
nFieldCount = nFieldCount + 1

Set loField = New clsField

lnDispositionPosition = InstrB(lnBoundaryStart, lnBytes,
CStrB("Content-Disposition"))

' Get an object name
lnStartPosition = InstrB(lnDispositionPosition, lnBytes, CStrB("name="))
+ 6
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(""""))
lsFieldName = CStrU(MidB(lnBytes, lnStartPosition, lnEndPosition -
lnStartPosition))
loField.FieldName = lsFieldName

' Get the location fo the file name.
lnFileNamePosition = InstrB(lnBoundaryStart, lnBytes, CStrB("filename="))
lnBoundaryEnd = InstrB(lnEndPosition, lnBytes, lnBoundaryBytes)

'Test if object is a file
If Not lnFileNamePosition = 0 And lnFileNamePosition < lnBoundaryEnd Then

' Parse Filename
lnStartPosition = lnFileNamePosition + 10
lnEndPosition = InstrB(lnStartPosition, lnBytes, CStrB(""""))
lsFileName =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.FileName = lsFileName

' Parse Content-Type
lnStartPosition = InstrB(lnEndPosition,lnBytes,CStrB("Content-Type:")) +
14
lnEndPosition = InstrB(lnStartPosition,lnBytes,CStrB(vbCr))
ContentType =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.ContentType = ContentType

' Parse Content
lnStartPosition = lnEndPosition + 4
lnEndPosition = InstrB(lnStartPosition,lnBytes,lnBoundaryBytes)-2
Value = MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition)
loField.BinaryData = Value & CStrB(vbNull)
loField.Length = LenB(Value)
Else

' Parse Content
lnStartPosition = InstrB(lnDispositionPosition, lnBytes, CStrB(vbCr)) +
4
lnEndPosition = InstrB(lnStartPosition, lnBytes, lnBoundaryBytes) - 2
Value =
CStrU(MidB(lnBytes,lnStartPosition,lnEndPosition-lnStartPosition))
loField.Value = Value
loField.Length = Len(Value)
End If

Set oFields(UBound(oFields)) = loField

'Loop to next object
lnBoundaryStart = InstrB(lnBoundaryStart + LenB(lnBoundaryBytes),
lnBytes, lnBoundaryBytes)

Set loField = Nothing

Loop

End Sub
' --------------------------------------------------------------------------
----
Private Function CStrU(ByRef psByteString)
Dim lnLength
Dim lnPosition
lnLength = LenB(psByteString)
For lnPosition = 1 To lnLength
CStrU = CStrU & Chr(AscB(MidB(psByteString, lnPosition, 1)))
Next
End Function
' --------------------------------------------------------------------------
----
Private Function CStrB(ByRef psUnicodeString)
Dim lnLength
Dim lnPosition
lnLength = Len(psUnicodeString)
For lnPosition = 1 To lnLength
CStrB = CStrB & ChrB(AscB(Mid(psUnicodeString, lnPosition, 1)))
Next
End Function
' --------------------------------------------------------------------------' --------------------------------------------------------------------------
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top