I have five fields
1.CustomerID
2.BusinessID
3.OfferID
4.Day of Purchase
5.Month Of Purchase
Private Function MakeCouponCode(ByVal sn As Int16) As String
Dim a(16) As Char
Dim chk As Int16
Dim check, tDate, slNo, couponCode As String
'..............................setting customerID
If HFCustID.Value.Length = 1 Then
HFCustID.Value = "00" & HFCustID.Value
ElseIf HFCustID.Value.Length = 2 Then
HFCustID.Value = "0" & HFCustID.Value
End If
'..............................setting businessID
If HFBusiID.Value.Length = 1 Then
HFBusiID.Value = "0" & HFBusiID.Value
End If
'..............................setting offerID
If HFOfferID.Value.Length = 1 Then
HFOfferID.Value = "0" & HFOfferID.Value
End If
'..............................setting todays date as ddmm
If Today.Day.ToString.Length = 1 Then
tDate = "0" & Today.Day.ToString
Else
tDate = Today.Day.ToString
End If
If Today.Month.ToString.Length = 1 Then
tDate = tDate & "0" & Today.Month.ToString
Else
tDate = tDate & Today.Month.ToString
End If
'...............................calculating and setting the check digits
If sn < 10 Then
slNo = "0" & Convert.ToString(sn)
Else
slNo = Convert.ToString(sn)
End If
'...............................calculating and setting the check digits
chk = Convert.ToInt16(HFCustID.Value) + Convert.ToInt16(HFCustID.Value) + Convert.ToInt16(HFOfferID.Value) + Today.Day + Today.Month + sn
check = Convert.ToString(chk)
If check.Length = 1 Then
check = "00" & check
ElseIf check.Length = 2 Then
check = "0" & check
End If
'...............................concatenate all for coupon code
couponCode = HFCustID.Value & HFBusiID.Value & HFOfferID.Value & tDate & slNo & check
Return couponCode
End Function
I am using the above code to make a CouponCode...but somehow its not very hard to crack...Any idea how can i make a bullet proof coupon code in not more than 16 digits????
If I understand you correctly, you're generating a 16-digit coup code, and then to validate it, you're using a sort of checksum?
If anyone figures out your checksum algorithm, they're going to be able to generated unlimited coupons.
I think it's better to pre-generate a few thousand or hundred thousand (however many you need) coupon codes, and perhaps make them one-time use (by deleting them or checking if they're already used).
Of course...this depends on your needs. A lot of sites just have easy-to-remember unlimited use coupon codes just to trick people into thinking they're getting a deal.
If you don't want people to be able to generate or guess valid coupon codes, consider using a cryptographic hash function.
One option is to use a hash function. On wikipedia you can find a whole list of them for various hash sizes and uses. With 16 digits you are looking at a 64 bit hash function which I would not call bullet proof.
1.CustomerID i guess at least 3 digits
2.BusinessID maybe 2 digits
3.OfferID 2 digits?
4.Day of Purchase 2 digits
5.Month Of Purchase 2 digits
so in total 11 digits. only 5 remaining.
I would create a longer code and then split it up into 2 parts
1. part are all information that you listed. If you like you can pseudo encrypt them by doing some weird calculations. only important that you can still easily read them
2. part is an encrypted hash from the first part. (take first part, use a hash function, encrypt the result of that hash with a password that only you know)
If someone enters a coupon, you can read all fields without problem, and the remaining fields are used to verify that it is a valid coupon. calculate hash again and encrypt it, and check if your calculation gives the same result. I would use at least 5 digits for the verification.
Here are the functions I use for hash and encryption. Make sure to add the System.Security.Cryptography. You should add those Salt numbers, and store in your program the password. just make sure it will not be readable in any way by users.
Imports System.Security.Cryptography
Imports System.Security
Imports System.Net.Sockets
Imports System.Text
Imports System.IO
Imports System
Namespace Crypt
Module Hash
Function MD5hash(ByVal data() As Byte) As Byte()
' This is one implementation of the abstract class MD5.
Dim md5 As New MD5CryptoServiceProvider()
Dim result As Byte() = md5.ComputeHash(data)
Return result
End Function
' Hash an input string and return the hash as
' a 32 character hexadecimal string.
Function getMd5Hash(ByVal input As String) As String
' Create a new instance of the MD5CryptoServiceProvider object.
Dim md5Hasher As New MD5CryptoServiceProvider()
' Convert the input string to a byte array and compute the hash.
Dim data As Byte() = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input))
' Create a new Stringbuilder to collect the bytes
' and create a string.
Dim sBuilder As New StringBuilder()
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
Dim i As Integer
For i = 0 To data.Length - 1
sBuilder.Append(data(i).ToString("x2"))
Next i
' Return the hexadecimal string.
Return sBuilder.ToString()
End Function
' Verify a hash against a string.
Function verifyMd5Hash(ByVal input As String, ByVal hash As String) As Boolean
' Hash the input.
Dim hashOfInput As String = getMd5Hash(input)
' Create a StringComparer an compare the hashes.
Dim comparer As StringComparer = StringComparer.OrdinalIgnoreCase
If 0 = comparer.Compare(hashOfInput, hash) Then
Return True
Else
Return False
End If
End Function
End Module
Module Crypto
''' <summary>
''' Encrypts data with Hash from passToHash
''' </summary>
''' <param name="data"></param>
''' <param name="passToHash"></param>
''' <returns></returns>
''' <remarks></remarks>
Function EncryptWithHash(ByVal data As String, ByVal passToHash As String) As String
Dim _hash As String = getMd5Hash(passToHash)
Dim _result As String = Encrypt(data, _hash)
Return _result
End Function
''' <summary>
''' Decrypts data with Hash from passToHash
''' </summary>
''' <param name="data"></param>
''' <param name="passToHash"></param>
''' <returns>can throw exception</returns>
''' <remarks></remarks>
Function DecryptWithHash(ByVal data As String, ByVal passToHash As String) As String
Dim _hash As String = getMd5Hash(passToHash)
Dim _result As String = Encrypt(data, _hash)
Return _result
End Function
''' <summary>
''' Creates a hash and encrypts it
''' </summary>
''' <param name="data"></param>
''' <param name="password"></param>
''' <returns></returns>
''' <remarks></remarks>
Function SigCreate(ByVal data As String, ByVal password As String) As String
Dim _hash As String = getMd5Hash(data)
Dim _crypt As String = Encrypt(_hash, password)
Return _crypt
End Function
''' <summary>
''' Verifies, if the encrypted Hash is valid
''' </summary>
''' <param name="data"></param>
''' <param name="password"></param>
''' <param name="enc"></param>
''' <returns></returns>
''' <remarks></remarks>
Function SigCheck(ByVal data As String, ByVal password As String, ByVal enc As String) As Boolean
Try
Dim _dec As String = Decrypt(enc, password)
Return verifyMd5Hash(data, _dec)
Catch ex As Exception
End Try
Return False
End Function
Private Salt As Byte() = {51, 39, 204, 201, 190, 167, 217, 190, _
56, 110, 254, 186, 23, 56, 117, 222, _
214, 32, 28, 16, 27, 23, 31, 211, _
101, 92, 143, 234, 45, 63, 75, 82}
''' <summary>
''' Encrypts Data with the given password
''' </summary>
''' <param name="Data"></param>
''' <param name="Password"></param>
''' <returns></returns>
''' <remarks></remarks>
Function Encrypt(ByVal data As String, ByVal password As String) As String
Dim pdb As New Rfc2898DeriveBytes(password, Salt)
Dim alg As Rijndael = Rijndael.Create()
alg.Key = pdb.GetBytes(32)
alg.IV = pdb.GetBytes(16)
Dim ms As New IO.MemoryStream
Dim cs As New CryptoStream(ms, alg.CreateEncryptor, CryptoStreamMode.Write)
cs.Write(System.Text.Encoding.Default.GetBytes(data), 0, data.Length)
cs.Close()
ms.Close()
Return Convert.ToBase64String(ms.ToArray)
End Function
''' <summary>
''' Decrypts Data with the given password
''' </summary>
''' <param name="Data"></param>
''' <param name="Password"></param>
''' <returns></returns>
''' <remarks>can throw exception</remarks>
Function Decrypt(ByVal data As String, ByVal password As String) As String
Dim pdb As New Rfc2898DeriveBytes(password, Salt)
Dim alg As Rijndael = Rijndael.Create()
alg.Key = pdb.GetBytes(32)
alg.IV = pdb.GetBytes(16)
Dim ms As New IO.MemoryStream
Dim cs As New CryptoStream(ms, alg.CreateDecryptor, CryptoStreamMode.Write)
cs.Write(Convert.FromBase64String(data), 0, Convert.FromBase64String(data).Length)
cs.Close()
ms.Close()
Return System.Text.Encoding.Default.GetString(ms.ToArray)
End Function
End Module
End Namespace
Related
im making a simply app to download torrent files, using MonoTorrent. But i cant load the torrent properly, and I've looked all available information.
That's the code im using:
Imports MonoTorrent.BEncoding
Imports MonoTorrent.Client
Imports MonoTorrent.Client.Tracker
Imports MonoTorrent.Common
Imports System.IO
Imports System.Net
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class
Module BitTorrentAnnounceReader
Sub main()
'load Torrentfile
Dim TorrentFile As torrent = ("D:\youtorrent.torrent")
Console.WriteLine(TorrentFile.Name)
'generate annouce paramters
'since we simluate a BitTornado Client double check PeerID and Key Paramter
Dim AnnounceParameter As New AnnounceParameters
AnnounceParameter.BytesLeft = TorrentFile.Size
AnnounceParameter.BytesUploaded = 0
AnnounceParameter.BytesDownloaded = 0
AnnounceParameter.Port = 12224
AnnounceParameter.InfoHash = TorrentFile.InfoHash
AnnounceParameter.PeerId = "T03I-----" & GenerateTorrentClientKeys(11, 1)
AnnounceParameter.ClientEvent = TorrentEvent.Started
'a torrentfile can have more than one url, we use only the first one
'the url should have http to work for this example
Dim AnnounceUrl As String = TorrentFile.AnnounceUrls.Item(0).Item(0).ToString
Console.WriteLine(AnnounceUrl)
'the full announceurl that will fired to tracker
'we are simulating a BitTorando Client
Dim FullAnnounceUrl As String = CreateAnnounceString(AnnounceParameter, AnnounceUrl, GenerateTorrentClientKeys(6))
'building a webrequest for tracker request; some silly line look at comments on
'MonoTorrent.Client.Tracker.HTTPTracker.Announce
Dim req As HttpWebRequest = CType(WebRequest.Create(FullAnnounceUrl), HttpWebRequest)
req.KeepAlive = False
req.Proxy = New WebProxy
'we want to simulate a BitTornado Client, so http headers
req.UserAgent = "User-Agent: BitTornado/T-0.3.18"
'to simulate full client we need also gzip but for better usage we dont use it
' req.Headers.Add("Accept-Encoding", "gzip")
' If (resp.ContentEncoding.ToLower().Contains("gzip")) Then
' Str = New IO.Compression.GZipStream(Str, IO.Compression.CompressionMode.Decompress)
Dim response As HttpWebResponse = req.GetResponse
Dim fs As Stream = WebResponseToStream(response)
Dim peers As List(Of Peer) = AnnounceGetPeerList(fs)
Console.WriteLine("Tracker returned:" & peers.Count)
For Each PeerInfo As Peer In peers
Console.WriteLine(PeerInfo.ConnectionUri.Host & ":" & PeerInfo.ConnectionUri.Port)
Next
Console.ReadKey()
End Sub
''' <summary>
''' Generate a random key depending on which TorrentClient to simulate
''' </summary>
''' <param name="len"></param>
''' <param name="keys"></param>
''' <returns></returns>
''' <remarks></remarks>
Function GenerateTorrentClientKeys(ByVal len As Integer, Optional ByVal keys As Integer = 1) As String
Dim Chars() As String = {"abcdefghijklmnopqrstuvwxyz0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}
'Chars[0] = uTorrent Keys
'Chars[1] = BitTornado Keys
Dim str As String = ""
Dim r As New System.Random()
For i = 1 To len
str &= Chars(keys).Substring(r.Next(1, Chars(keys).Length), 1)
Next
Return str
End Function
''' <summary>
''' A simple way of parsing a bencoded peerlist. it will autodecode compact mode request
''' you can find the full announce parser in the orignal file:
'''
''' MonoTorrent.Client.Tracker.HTTPTracker.HandleAnnounce
''' http://anonsvn.mono-project.com/viewvc/trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Tracker/HTTPTracker.cs
''' </summary>
''' <param name="fs"></param>
''' <returns></returns>
''' <remarks></remarks>
Function AnnounceGetPeerList(ByVal fs As Stream) As List(Of Peer)
'you can also use a file with a torrenrequest
'Dim reader As New RawReader(IO.File.Open("file.req", IO.FileMode.Open), False)
'decode the bencoded stream
Dim dictionary As BEncodedDictionary = BEncodedValue.Decode(Of BEncodedDictionary)(fs)
Dim peers As New List(Of Peer)
For Each keypair In dictionary
Select Case keypair.Key.ToString
Case "interval"
'MsgBox TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString()));
'MsgBox(keypair.Value.ToString)
Case "peers"
If TypeOf keypair.Value Is BEncodedList Then
peers.AddRange(Peer.Decode(DirectCast(keypair.Value, BEncodedList)))
ElseIf TypeOf keypair.Value Is BEncodedString Then
peers.AddRange(Peer.Decode(DirectCast(keypair.Value, BEncodedString)))
End If
Case Else
'MsgBox("HttpTracker - Unknown announce tag received:" & keypair.Key.ToString() & keypair.Value.ToString())
End Select
Next
Return peers
End Function
''' <summary>
''' Original CreateAnnounceString is private only and we need to modify it a little bit; this the old one out of svn
''' they have created here a better function that uses UriQueryBuilder but its oversized here
'''
''' MonoTorrent.Client.Tracker.HTTPTracker.CreateAnnounceString
''' http://anonsvn.mono-project.com/viewvc/trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Tracker/HTTPTracker.cs?revision=141866
''' </summary>
''' <param name="parameters"></param>
''' <param name="Uri">AnnounceURL of the TorrentFile</param>
''' <param name="Key">a radon key paramter</param>
''' <returns>url to use with a WebRequest</returns>
''' <remarks></remarks>
Private Function CreateAnnounceString(ByVal parameters As AnnounceParameters, ByVal Uri As String, ByVal Key As String) As String
Dim sb As New System.Text.StringBuilder(256)
'base.LastUpdated = DateTime.Now;
' FIXME: This method should be tidied up. I don't like the way it current works
sb.Append(Uri)
sb.Append(If(Uri.Contains("?"), "&"c, "?"c))
sb.Append("info_hash=")
sb.Append(parameters.InfoHash.UrlEncode())
sb.Append("&peer_id=")
sb.Append(parameters.PeerId)
sb.Append("&port=")
sb.Append(parameters.Port)
If parameters.SupportsEncryption Then
sb.Append("&supportcrypto=1")
End If
If parameters.RequireEncryption Then
sb.Append("&requirecrypto=1")
End If
sb.Append("&uploaded=")
sb.Append(parameters.BytesUploaded)
sb.Append("&downloaded=")
sb.Append(parameters.BytesDownloaded)
sb.Append("&left=")
sb.Append(parameters.BytesLeft)
sb.Append("&compact=1")
' Always use compact response
sb.Append("&numwant=")
sb.Append(100)
If Not Uri.Contains("&key=") AndAlso Not Uri.Contains("?key=") Then
sb.Append("&key=")
' The 'key' protocol, used as a kind of 'password'. Must be the same between announces
sb.Append(Key)
End If
If parameters.Ipaddress IsNot Nothing Then
sb.Append("&ip=")
sb.Append(parameters.Ipaddress)
End If
' If we have not successfully sent the started event to this tier, override the passed in started event
' Otherwise append the event if it is not "none"
'if (!parameters.Id.Tracker.Tier.SentStartedEvent)
'{
' sb.Append("&event=started");
' parameters.Id.Tracker.Tier.SendingStartedEvent = true;
'}
If parameters.ClientEvent <> TorrentEvent.None Then
sb.Append("&event=")
sb.Append(parameters.ClientEvent.ToString().ToLower())
End If
Return sb.ToString()
End Function
''' <summary>
''' HttpWebResponse and GetResponseStream dont gives use a full readable stream so we must convert it
'''
''' Look at: MonoTorrent.Client.Tracker.HTTPTracker.DecodeResponse
''' http://anonsvn.mono-project.com/viewvc/trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Tracker/HTTPTracker.cs
''' or
''' http://bytes.com/topic/c-sharp/answers/232436-download-binary-file-http#post949811
''' </summary>
''' <param name="response"></param>
''' <returns></returns>
''' <remarks></remarks>
Function WebResponseToStream(ByVal response As HttpWebResponse) As Stream
Dim responseStream As Stream = response.GetResponseStream
Dim fs As MemoryStream = New MemoryStream(256)
Dim buffer As Byte() = New Byte(4095) {}
Dim length As Integer = responseStream.Read(buffer, 0, 4096)
While length > 0
fs.Write(buffer, 0, length)
length = responseStream.Read(buffer, 0, 4096)
End While
fs.Seek(0, SeekOrigin.Begin)
Return fs
End Function
End Module
The problem only appears in the load file .torrent part:
Dim TorrentFile As **torrent** = ("D:\youtorrent.torrent")
Vb.net throws me an error of "Type expected 'on the text torrent. there any solution? Thanks to all!
Try
Dim TorrentFile As torrent = Torrent.Load("D:\youtorrent.torrent")
I found this code in order to do a PHP Post in VB.NET with params, however I don't really understand how to also send a file with it as well?
My PHP page watches for $_POST["file"] and I just need to be able to send foo=bar & foo2=bar to my PHP page, and also upload "file" as well.
Here is the method I been using so far and seems to be working OK with posting the foo and foo2
Public Function PHP(ByVal url As String, ByVal method As String, ByVal data As String)
Try
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create(url)
request.Method = method
Dim postData = data
Dim byteArray As Byte() = System.Text.Encoding.UTF8.GetBytes(postData)
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = byteArray.Length
Dim dataStream As Stream = request.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
dataStream.Close()
Dim response As WebResponse = request.GetResponse()
dataStream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()
reader.Close()
dataStream.Close()
response.Close()
Return (responseFromServer)
Catch ex As Exception
Dim error1 As String = ErrorToString()
If error1 = "Invalid URI: The format of the URI could not be determined." Then
MsgBox("ERROR! Must have HTTP:// before the URL.")
Else
MsgBox(error1)
End If
Return ("ERROR")
End Try
End Function
I found an awesome class a guy named Greg wrote originally in C# that I had gotten converted to VB.NET and it works beautifully. It was found on: http://www.c-sharpcorner.com/UploadFile/gregoryprentice/DotNetBugs12062005230632PM/DotNetBugs.aspx
To use code below..
Dim form As New MultipartForm(URL)
form.setField("param1", "foo")
form.setField("param2", "bar")
form.sendFile("C:\test.PDF")
Dim Response as String = form.ResponseText.ToString
Below is the actual in case the URL ever breaks because its such a great piece of code which is now in VB.NET
Imports System.Net
Imports System.Text
Imports System.IO
Imports System.Collections
Namespace norvanco.http
''' <summary>
''' Allow the transfer of data files using the W3C's specification
''' for HTTP multipart form data. Microsoft's version has a bug
''' where it does not format the ending boundary correctly.
''' Written by: gregoryp#norvanco.com
''' </summary>
Public Class MultipartForm
''' <summary>
''' Holds any form fields and values that you
''' wish to transfer with your data.
''' </summary>
Private coFormFields As Hashtable
''' <summary>
''' Used mainly to avoid passing parameters to other routines.
''' Could have been local to sendFile().
''' </summary>
Protected coRequest As HttpWebRequest
''' <summary>
''' Used if we are testing and want to output the raw
''' request, minus http headers, out to a file.
''' </summary>
Private coFileStream As System.IO.Stream
''' <summary>
''' Difined to build the form field data that is being
''' passed along with the request.
''' </summary>
Shared CONTENT_DISP As String = "Content-Disposition: form-data; name="
''' <summary>
''' Allows you to specify the specific version of HTTP to use for uploads.
''' The dot NET stuff currently does not allow you to remove the continue-100 header
''' from 1.1 and 1.0 currently has a bug in it where it adds the continue-100. MS
''' has sent a patch to remove the continue-100 in HTTP 1.0.
''' </summary>
Public Property TransferHttpVersion() As Version
Get
Return coHttpVersion
End Get
Set(ByVal value As Version)
coHttpVersion = value
End Set
End Property
Private coHttpVersion As Version
''' <summary>
''' Used to change the content type of the file being sent.
''' Currently defaults to: text/xml. Other options are
''' text/plain or binary
''' </summary>
Public Property FileContentType() As String
Get
Return coFileContentType
End Get
Set(ByVal value As String)
coFileContentType = value
End Set
End Property
Private coFileContentType As String
''' <summary>
''' Initialize our class for use to send data files.
''' </summary>
''' <param name="url">The web address of the recipient of the data transfer.</param>
Public Sub New(ByVal url__1 As String)
URL = url__1
coFormFields = New Hashtable()
ResponseText = New StringBuilder()
BufferSize = 1024 * 10
BeginBoundary = "ou812--------------8c405ee4e38917c"
TransferHttpVersion = HttpVersion.Version11
FileContentType = "text/xml"
End Sub
'---------- BEGIN PROPERTIES SECTION ----------
Private _BeginBoundary As String
''' <summary>
''' The string that defines the begining boundary of
''' our multipart transfer as defined in the w3c specs.
''' This method also sets the Content and Ending
''' boundaries as defined by the w3c specs.
''' </summary>
Public Property BeginBoundary() As String
Get
Return _BeginBoundary
End Get
Set(ByVal value As String)
_BeginBoundary = value
ContentBoundary = Convert.ToString("--") & BeginBoundary
EndingBoundary = ContentBoundary & Convert.ToString("--")
End Set
End Property
''' <summary>
''' The string that defines the content boundary of
''' our multipart transfer as defined in the w3c specs.
''' </summary>
Protected Property ContentBoundary() As String
Get
Return _ContentBoundary
End Get
Set(ByVal value As String)
_ContentBoundary = value
End Set
End Property
Private _ContentBoundary As String
''' <summary>
''' The string that defines the ending boundary of
''' our multipart transfer as defined in the w3c specs.
''' </summary>
Protected Property EndingBoundary() As String
Get
Return _EndingBoundary
End Get
Set(ByVal value As String)
_EndingBoundary = value
End Set
End Property
Private _EndingBoundary As String
''' <summary>
''' The data returned to us after the transfer is completed.
''' </summary>
Public Property ResponseText() As StringBuilder
Get
Return _ResponseText
End Get
Set(ByVal value As StringBuilder)
_ResponseText = value
End Set
End Property
Private _ResponseText As StringBuilder
''' <summary>
''' The web address of the recipient of the transfer.
''' </summary>
Public Property URL() As String
Get
Return _URL
End Get
Set(ByVal value As String)
_URL = value
End Set
End Property
Private _URL As String
''' <summary>
''' Allows us to determine the size of the buffer used
''' to send a piece of the file at a time out the IO
''' stream. Defaults to 1024 * 10.
''' </summary>
Public Property BufferSize() As Integer
Get
Return _BufferSize
End Get
Set(ByVal value As Integer)
_BufferSize = value
End Set
End Property
Private _BufferSize As Integer
'---------- END PROPERTIES SECTION ----------
''' <summary>
''' Used to signal we want the output to go to a
''' text file verses being transfered to a URL.
''' </summary>
''' <param name="path"></param>
Public Sub setFilename(ByVal path As String)
coFileStream = New System.IO.FileStream(path, FileMode.Create, FileAccess.Write)
End Sub
''' <summary>
''' Allows you to add some additional field data to be
''' sent along with the transfer. This is usually used
''' for things like userid and password to validate the
''' transfer.
''' </summary>
''' <param name="key">The form field name</param>
''' <param name="str">The form field value</param>
Public Sub setField(ByVal key As String, ByVal str As String)
coFormFields(key) = str
End Sub
''' <summary>
''' Determines if we have a file stream set, and returns either
''' the HttpWebRequest stream of the file.
''' </summary>
''' <returns></returns>
Public Overridable Function getStream() As System.IO.Stream
Dim io As System.IO.Stream
If coFileStream Is Nothing Then
io = coRequest.GetRequestStream()
Else
io = coFileStream
End If
Return io
End Function
''' <summary>
''' Here we actually make the request to the web server and
''' retrieve it's response into a text buffer.
''' </summary>
Public Overridable Sub getResponse()
If coFileStream Is Nothing Then
Dim io As System.IO.Stream
Dim oResponse As WebResponse
Try
oResponse = coRequest.GetResponse()
Catch web As WebException
oResponse = web.Response
End Try
If oResponse IsNot Nothing Then
io = oResponse.GetResponseStream()
Dim sr As New StreamReader(io)
Dim str As String
ResponseText.Length = 0
While (InlineAssignHelper(str, sr.ReadLine())) IsNot Nothing
ResponseText.Append(str)
End While
oResponse.Close()
Console.Write(ResponseText)
Else
Throw New Exception("MultipartForm: Error retrieving server response")
End If
End If
End Sub
''' <summary>
''' Transmits a file to the web server stated in the
''' URL property. You may call this several times and it
''' will use the values previously set for fields and URL.
''' </summary>
''' <param name="aFilename">The full path of file being transfered.</param>
Public Sub sendFile(ByVal aFilename As String)
' The live of this object is only good during
' this function. Used mainly to avoid passing
' around parameters to other functions.
coRequest = DirectCast(WebRequest.Create(URL), HttpWebRequest)
' Set use HTTP 1.0 or 1.1.
coRequest.ProtocolVersion = TransferHttpVersion
coRequest.Method = "POST"
coRequest.ContentType = Convert.ToString("multipart/form-data; boundary=") & BeginBoundary
coRequest.Headers.Add("Cache-Control", "no-cache")
coRequest.KeepAlive = True
Dim strFields As String = getFormfields()
Dim strFileHdr As String = getFileheader(aFilename)
Dim strFileTlr As String = getFiletrailer()
Dim info As New FileInfo(aFilename)
coRequest.ContentLength = strFields.Length + strFileHdr.Length + strFileTlr.Length + info.Length
Dim io As System.IO.Stream
io = getStream()
writeString(io, strFields)
writeString(io, strFileHdr)
Me.writeFile(io, aFilename)
writeString(io, strFileTlr)
getResponse()
io.Close()
' End the life time of this request object.
coRequest = Nothing
End Sub
''' <summary>
''' Mainly used to turn the string into a byte buffer and then
''' write it to our IO stream.
''' </summary>
''' <param name="io">The io stream for output.</param>
''' <param name="str">The data to write.</param>
Public Sub writeString(ByVal io As System.IO.Stream, ByVal str As String)
Dim PostData As Byte() = System.Text.Encoding.ASCII.GetBytes(str)
io.Write(PostData, 0, PostData.Length)
End Sub
''' <summary>
''' Builds the proper format of the multipart data that
''' contains the form fields and their respective values.
''' </summary>
''' <returns>The data to send in the multipart upload.</returns>
Public Function getFormfields() As String
Dim str As String = ""
Dim myEnumerator As IDictionaryEnumerator = coFormFields.GetEnumerator()
While myEnumerator.MoveNext()
str += (Convert.ToString(ContentBoundary & Convert.ToString(vbCr & vbLf)) & CONTENT_DISP) + """"c + myEnumerator.Key + """" & vbCr & vbLf & vbCr & vbLf + myEnumerator.Value + vbCr & vbLf
End While
Return str
End Function
''' <summary>
''' Returns the proper content information for the
''' file we are sending.
''' </summary>
''' <remarks>
''' Hits Patel reported a bug when used with ActiveFile.
''' Added semicolon after sendfile to resolve that issue.
''' Tested for compatibility with IIS 5.0 and Java.
''' </remarks>
''' <param name="aFilename"></param>
''' <returns></returns>
Public Function getFileheader(ByVal aFilename As String) As String
Return (Convert.ToString((Convert.ToString(ContentBoundary & Convert.ToString(vbCr & vbLf)) & CONTENT_DISP) + """file1""; filename=""" + Path.GetFileName(aFilename) + """" & vbCr & vbLf + "Content-type: ") & FileContentType) + vbCr & vbLf & vbCr & vbLf
End Function
''' <summary>
''' Creates the proper ending boundary for the multipart upload.
''' </summary>
''' <returns>The ending boundary.</returns>
Public Function getFiletrailer() As String
Return Convert.ToString(vbCr & vbLf) & EndingBoundary
End Function
''' <summary>
''' Reads in the file a chunck at a time then sends it to the
''' output stream.
''' </summary>
''' <param name="io">The io stream to write the file to.</param>
''' <param name="aFilename">The name of the file to transfer.</param>
Public Sub writeFile(ByVal io As System.IO.Stream, ByVal aFilename As String)
Dim readIn As New FileStream(aFilename, FileMode.Open, FileAccess.Read)
readIn.Seek(0, SeekOrigin.Begin)
' move to the start of the file
Dim fileData As Byte() = New Byte(BufferSize - 1) {}
Dim bytes As Integer
While (InlineAssignHelper(bytes, readIn.Read(fileData, 0, BufferSize))) > 0
' read the file data and send a chunk at a time
io.Write(fileData, 0, bytes)
End While
readIn.Close()
End Sub
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
End Class
End Namespace
I have a text file containing the properties for a virtual server running on my machine. I would like to be able to edit those properties from a GUI built with VB 2008. The Properties file is pre-generated with default values and I would like to change those values to fit my needs.
The Properties file is formatted as follows:
Item-One=ValueOne
Item-Two=ValueTwo
Item-Three=OtherLongValue
etc.
What I need is to be able to select the property based off it's name (Item-Two) and then remove the original value (which may be unknown) and place in my custom value. Values are String type.
I have already tried two suggestions, but neither achieve my goal.
Attempt1:
System.IO.File.WriteAllText(propName, System.IO.File.ReadAllText(propName).Replace("initial", "final"))
Attempt2:
Dim thefile As String = PropertyFileName
Dim lines() As String = System.IO.File.ReadAllLines(thefile)
lines(28) = "Item-Example=" + myValue
System.IO.File.WriteAllLines(thefile, lines)
Number One does not work because it requires me to know the original value, which I do not.
Number Two "works" but often adds new lines instead of replacing the old.
Here is a class I made. It is also documented which should help with inteliSense. Bellow I added some example of its usage.
SettingManager.vb
''' <summary>
''' Manages Settings which can be loaded and saved to a file specified
''' </summary>
''' <remarks></remarks>
Public Class SettingManager
Private filePath As String
Private prop As New Dictionary(Of String, String)
''' <summary>
''' Create a new SettingManager and loads settings from file specified.
''' If file specified doesnt exist, a new one is created upon save()
''' </summary>
''' <param name="filePath">Setting file to load</param>
''' <remarks></remarks>
Sub New(ByVal filePath As String)
Me.filePath = filePath
If (Not System.IO.File.Exists(filePath)) Then
Return
End If
Using reader As System.IO.StreamReader = New System.IO.StreamReader(filePath)
Dim line As String
line = reader.ReadLine()
'Loop through the lines and add each setting to the dictionary: prop
Do While (Not line Is Nothing)
'Spit the line into setting name and value
Dim tmp(2) As String
tmp = line.Split("=")
Me.AddSetting(tmp(0), tmp(1))
line = reader.ReadLine()
Loop
End Using
End Sub
''' <summary>
''' Get value of specified setting if exists.
''' If setting doesnt exist, KeyNotFound exception is thrown
''' </summary>
''' <param name="name">Name of setting</param>
''' <returns>Value of setting</returns>
Function GetSetting(ByVal name As String) As String
If (Not prop.ContainsKey(name)) Then
Throw New KeyNotFoundException("Setting: " + name + " not found")
End If
Return prop(name)
End Function
''' <summary>
''' Adds a new setting.
''' </summary>
''' <param name="name">Name of setting</param>
''' <param name="value">Value of setting</param>
''' <remarks>Save() function should be called to save changes</remarks>
Sub AddSetting(ByVal name As String, ByVal value As String)
If (prop.ContainsKey(name)) Then
prop(name) = value
Else
prop.Add(name, value)
End If
End Sub
''' <summary>
''' Saves settings to file. Any new settings added are also saved
''' </summary>
''' <remarks></remarks>
Sub Save()
Using writer As System.IO.StreamWriter = New System.IO.StreamWriter(filePath)
For Each kvp As KeyValuePair(Of String, String) In Me.prop
writer.WriteLine(kvp.Key + "=" + kvp.Value)
Next
End Using
End Sub
End Class
How to use:
Create a new file in your project called SettingManager.vb
Copy the code above into it
Example Usage
Dim sm As New SettingManager("settings.txt")
'Get Setting
Console.WriteLine(sm.GetSetting("Item-One")) 'Value-One
'Change setting
pm.AddSetting("Item-One", "different_value")
Console.WriteLine(sm.GetSetting("Item-One")) 'different_value
'Add new Setting
pm.AddSetting("name", "Krimson")
Console.WriteLine(sm.GetSetting("name")) 'Krimson
'Save any changes made
sm.Save()
Note: The code is not robust enough. For example if a value contains an =, errors might occur since there is no check implemented to prevent this. However, this should be a good starting point
A little Addition
Do While (Not line Is Nothing)
If line = Nothing OrElse line.Length = 0 OrElse line.StartsWith("#") Then
'Continue Do
Else
'Spit the line into setting name and value
Dim tmp(2) As String
tmp = line.Split("=")
Me.AddSetting(tmp(0), tmp(1))
End If
line = reader.ReadLine()
Loop
Is there a way to check if a string has all of it's parenthesis closed? So for example it would take as an argument a string like this:
dim ValidOne as string = "This is (good)"
dim ValidOne as string = "This (is (good))"
dim InvalidOne as string = "This is (bad))"
dim InvalidOne as string = "This is (bad"
dim InvalidOne as string = "This is bad)"
And return True or False depending on whether there is a valid number of closed parenthesis.
So it if the string had an open ( and it was not closed, or just a ) that was never opened, it would return false.
I think you can do something like +1 for each open ( and -1 for each ). The rule is that you must end with 0 at the end.
If you want a full versatile and customizable solution then here is my approach:
Output:
Snippet:
''' <summary>
''' Counts the closed and opened pair of chars inside a String.
''' </summary>
''' <param name="PairChars">The pair character.</param>
''' <param name="Input">The string where to count the pair characters.</param>
''' <returns>PairCharacter.</returns>
''' <exception cref="System.Exception">Index of 'PairChar' parameter is out of range.</exception>
Public Function CountPairOfChars(ByVal PairChars As KeyValuePair(Of Char, Char),
ByVal Input As String) As PairOfCharsInfo
If String.IsNullOrEmpty(Input) OrElse String.IsNullOrWhiteSpace(Input) Then
Throw New Exception("'Input' parameter cannot be an empty String.")
End If
Dim CharStack As New Stack(Of Integer)
Dim Result As New PairOfCharsInfo
With Result
.Input = Input
.Characters = New KeyValuePair(Of Char, Char)(PairChars.Key, PairChars.Value)
For i As Integer = 0 To Input.Length - 1
Select Case Input(i)
Case .Characters.Key
CharStack.Push(i)
.OpenedPairsIndex.Add(i)
.CountOpenedPairs += 1
Case .Characters.Value
Select Case CharStack.Count
Case Is = 0
.CountOpenedPairs += 1
.OpenedPairsIndex.Add(i)
Case Else
.CountClosedPairs += 1
.CountOpenedPairs -= 1
.ClosedPairsIndex.Add(Tuple.Create(Of Integer, Integer)(CharStack.Pop, i))
.OpenedPairsIndex.RemoveAt(.OpenedPairsIndex.Count - 1)
End Select '/ CharStack.Count
End Select '/ Input(i)
Next i
.StringHasClosedPairs = .CountClosedPairs <> 0
.StringHasOpenedPairs = .CountOpenedPairs <> 0
End With '/ Result
Return Result
End Function
''' <summary>
''' Stores info about closed and opened pairs of chars in a String.
''' </summary>
Public NotInheritable Class PairOfCharsInfo
''' <summary>
''' Indicates the input string.
''' </summary>
''' <value>The input string.</value>
Public Property Input As String = String.Empty
''' <summary>
''' Indicates the pair of characters.
''' </summary>
''' <value>The pair of characters.</value>
Public Property Characters As KeyValuePair(Of Char, Char) = Nothing
''' <summary>
''' Determines whether the input string contains closed pairs of character.
''' </summary>
''' <value>The closed pairs count.</value>
Public Property StringHasClosedPairs As Boolean = False
''' <summary>
''' Determines whether the input string contains opened pairs of character.
''' </summary>
''' <value>The closed pairs count.</value>
Public Property StringHasOpenedPairs As Boolean = False
''' <summary>
''' Indicates the total amount of closed pairs.
''' </summary>
''' <value>The closed pairs count.</value>
Public Property CountClosedPairs As Integer = 0
''' <summary>
''' Indicates the total amount of opened pairs.
''' </summary>
''' <value>The opened pairs count.</value>
Public Property CountOpenedPairs As Integer = 0
''' <summary>
''' Indicates the closed pairs index position in the string.
''' </summary>
''' <value>The closed pairs positions.</value>
Public Property ClosedPairsIndex As New List(Of Tuple(Of Integer, Integer))
''' <summary>
''' Indicates the opened pairs index position in the string.
''' </summary>
''' <value>The opened pairs positions.</value>
Public Property OpenedPairsIndex As New List(Of Integer)
End Class '/ PairOfCharsInfo
Example Usage:
( The same as I used for the output images above)
Private Sub Test() Handles MyBase.Shown
Dim Inputs As String() =
{
"(This) is (good)",
"This (is (good))",
"This is good",
"This is (bad))",
"This is (bad",
"This is bad)",
"This is bad)("
}
Dim PairChars As New KeyValuePair(Of Char, Char)("(", ")")
For Each s As String In Inputs
Dim Info As PairOfCharsInfo = Me.CountPairOfChars(PairChars, s)
Dim sb As New System.Text.StringBuilder
With sb
.AppendLine(String.Format("Input String: {0}", Info.Input))
.AppendLine(String.Format("Pair of Chars: {0}{1}", Info.Characters.Key, Info.Characters.Value))
.AppendLine()
.AppendLine(String.Format("String has closed pairs?: {0}", Info.StringHasClosedPairs))
.AppendLine(String.Format("String has opened pairs?: {0}", Info.StringHasOpenedPairs))
.AppendLine()
.AppendLine(String.Format("Closed Pairs Count: {0}", Info.CountClosedPairs))
.AppendLine(String.Format("Opened Pairs Count: {0}", Info.CountOpenedPairs))
.AppendLine()
.AppendLine("Closed Pairs Indexes:")
For Each Item As Tuple(Of Integer, Integer) In Info.ClosedPairsIndex
.AppendLine(String.Format("Start Index: {0}, End Index: {1}",
CStr(Item.Item1), CStr(Item.Item2)))
Next Item
.AppendLine()
.AppendLine(String.Format("Opened Pairs Indexes: {0}",
String.Join(", ", Info.OpenedPairsIndex)))
End With '/ sb
MessageBox.Show(sb.ToString, "Count Pair Characters Information",
MessageBoxButtons.OK, MessageBoxIcon.Information)
Next s
End Sub
Something like this should do it:
Public Shared Function TestStringParens(s As String) As Boolean
Dim Ret = 0
For Each C In s
If C = ")"c Then Ret -= 1
If C = "("c Then Ret += 1
'Bail earlier for a closed paren without a matching open
If Ret < 0 Then Return False
Next
Return Ret = 0
End Function
As your post and some other people have said just keep a counter around and walk the string. As #Drico said, any time a negative counter exists then we have a closed parentheses without a corresponding open.
You can test this with:
Dim Tests As New Dictionary(Of String, Boolean)
Tests.Add("This is (good)", True)
Tests.Add("This (is (good))", True)
Tests.Add("This is good", True)
Tests.Add("This is (bad))", False)
Tests.Add("This is (bad", False)
Tests.Add("This is bad)", False)
Tests.Add("This is bad)(", False)
For Each T In Tests
Console.WriteLine(TestStringParens(T.Key) = T.Value)
Next
Here is an example of how you use the mid function to loop through a string
Function checkPar(s As String) As Boolean
Dim i As Integer
Dim parCounter As Integer
parCounter = 0
For i = 1 To Len(s)
If Mid(s, i, 1) = "(" Then
parCounter = parCounter + 1
ElseIf Mid(s, i, 1) = ")" Then
parCounter = parCounter - 1
End If
If parCounter < 0 Then Exit For
Next
If parCounter <> 0 Then
checkPar = False
Else
checkPar = True
End If
End Function
I am using VB.net VS2012 and am having trouble with getting a list of files with a filter.
Here is my code:
Public Function SearchAndAddToListWithFilter(ByVal path As String, ByVal Recursive As Boolean, arrayListOfFilters As ArrayList, ByRef listOfFiles As List(Of FileInfo))
If Not Directory.Exists(path) Then Exit Function
Dim initDirInfo As New DirectoryInfo(path)
For Each oFileInfo In initDirInfo.GetFiles
Application.DoEvents()
For x = 0 To arrayListOfFilters.Count - 1
If (oFileInfo.Name Like arrayListOfFilters(x)) Then
listOfFiles.Add(oFileInfo)
End If
Next
Next
If Recursive Then
For Each oDirInfo In initDirInfo.GetDirectories
SearchAndAddToListWithFilter(oDirInfo.FullName, True, arrayListOfFilters, listOfFiles)
Next
End If
End Function
And here is an example of how to use it:
Dim stringFilterList As String = "*.mp3, *.docx, *.mp3, *.txt"
Dim arrayListOfFilenameFilters As New ArrayList(stringFilterList.Split(","))
Dim stringFolderPath As String = "C:\temp\folder\"
Dim booleanSearchSubFolders As Boolean = True
Dim listOfFilesFoundViaSearch As New List(Of FileInfo)
SearchAndAddToListWithFilter(stringFolderPath, booleanSearchSubFolders, arrayListOfFilenameFilters, listOfFilesFoundViaSearch)
For x = 0 To listOfFilesFoundViaSearch.Count - 1
MsgBox(listOfFilesFoundViaSearch(x).FullName)
Next
For some reason, the code only adds the files to the list that satisy the first condition in the list of filters.
Can I please have some help to get this code working?
Thank you.
Functions return values, and passing a value ByRef is NOT the way to do it.
The following function will work:
Private Function SearchAndAddToListWithFilter(ByVal path As String, ByVal filters As String(), ByVal searchSubFolders As Boolean) As List(Of IO.FileInfo)
If Not IO.Directory.Exists(path) Then
Throw New Exception("Path not found")
End If
Dim searchOptions As IO.SearchOption
If searchSubFolders Then
searchOptions = IO.SearchOption.AllDirectories
Else
searchOptions = IO.SearchOption.TopDirectoryOnly
End If
Return filters.SelectMany(Function(filter) New IO.DirectoryInfo(path).GetFiles(filter, searchOptions)).ToList
End Function
and to use this function:
Dim filters As String() = {"*.mp3", "*.docx", "*.bmp", "*.txt"}
Dim path As String = "C:\temp\folder\"
Dim foundFiles As List(Of IO.FileInfo) = SearchAndAddToListWithFilter(path, filters, True)
The solution provided by #Steve really shows the .NET way of doing the task.
However I used a recursive solution with possible definitions of maximum depth and/or duration. For completeness of this topic, I want to post the code:
''' <summary>
''' Search files in directory and subdirectories
''' </summary>
''' <param name="searchDir">Start Directory</param>
''' <param name="searchPattern">Search Pattern</param>
''' <param name="maxDepth">maximum depth; 0 for unlimited depth</param>
''' <param name="maxDurationMS">maximum duration; 0 for unlimited duration</param>
''' <returns>a list of filenames including the path</returns>
''' <remarks>
''' recursive use of Sub dirS
'''
''' wallner-novak#bemessung.at
''' </remarks>
Public Shared Function dirRecursively(searchDir As String, searchPattern As String, _
Optional maxDepth As Integer = 0, _
Optional maxDurationMS As Long = 0) As List(Of String)
Dim fileList As New List(Of String)
Dim depth As Integer = 0
Dim sw As New Stopwatch
dirS(searchDir, searchPattern, maxDepth, maxDurationMS, fileList, depth, sw)
Return fileList
End Function
''' <summary>
''' Recursive file search
''' </summary>
''' <param name="searchDir">Start Directory</param>
''' <param name="searchPattern">Search Pattern</param>
''' <param name="maxDepth">maximum depth; 0 for unlimited depth</param>
''' <param name="maxDurationMS">maximum duration; 0 for unlimited duration</param>
''' <param name="fileList">Filelist to append to</param>
''' <param name="depth">current depth</param>
''' <param name="sw">stopwatch</param>
''' <param name="quit">boolean value to quit early (at given depth or duration)</param>
''' <remarks>
''' wallner-novak#bemessung.at
''' </remarks>
Private Shared Sub dirS(searchDir As String, searchPattern As String, _
Optional maxDepth As Integer = 0, _
Optional maxDurationMS As Long = 0, _
Optional ByRef fileList As List(Of String) = Nothing, _
Optional ByRef depth As Integer = 0, _
Optional ByRef sw As Stopwatch = Nothing, _
Optional ByRef quit As Boolean = False)
If maxDurationMS > 0 Then
If depth = 0 Then
sw = New Stopwatch
sw.Start()
Else
If sw.ElapsedMilliseconds > maxDurationMS Then
quit = True
Exit Sub
End If
End If
End If
If maxDepth > 0 Then
If depth > maxDepth Then
quit = True
Exit Sub
End If
End If
' check if directory exists
If Not Directory.Exists(searchDir) Then
Exit Sub
End If
' find files
For Each myFile As String In Directory.GetFiles(searchDir, searchPattern)
fileList.Add(myFile)
Next
' recursively scan subdirectories
For Each myDir In Directory.GetDirectories(searchDir)
depth += 1
dirS(myDir, searchPattern, maxDepth, maxDurationMS, fileList, depth, sw, quit)
If quit Then Exit For
depth -= 1
Next
End Sub
ListView1.Items.Clear()
For Each files As String In System.IO.Directory.GetFiles(cmb_Drives.SelectedItem.ToString, txtSearch.Text)
Dim ico As Icon = System.Drawing.Icon.ExtractAssociatedIcon(files)
ImageList1.Images.Add(ico)
Dim list As ListViewItem = New ListViewItem(My.Computer.FileSystem.GetFileInfo(files).FullName, ImageList1.Images.Count - 1)
ListView1.Items.Add(list)
Next