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
Related
I want to search a specific part of a string in VB.NET. For example in the string below I want the following part: "Tennis".
Football ... Basketball ... Tennis ... Golf
I'm not sure how I would crop out the other part of the string so that im left with Tennis. Thanks :)
The solution below is my thought... You can use this function in any class you want, you pass it the string you want to check, what we should split on and finally what position do we want to get... I hope you do not mind Linq and lamda expression's...
''' <summary>
''' Return's word at index if it exist.
''' </summary>
''' <param name="Sentence"></param>
''' <param name="SplitString"></param>
''' <param name="Position"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function GetWordAtPosition(ByVal Sentence As String, ByVal SplitString As String, ByVal Position As Integer) As String
Dim ReturnWord As String = String.Empty
Dim ListPossibleWords As New List(Of String)
Try
'First see if we have a string, it's not empty or null, we have something to split on, and the actual word
'at the given position...
If Sentence IsNot Nothing AndAlso Not String.IsNullOrEmpty(Sentence) AndAlso SplitString IsNot Nothing AndAlso Not String.IsNullOrEmpty(SplitString) AndAlso Position > -1 Then
'Trim the string out...
Sentence = Sentence.Trim.Replace(" ", String.Empty)
'Does the string have what we need to split on?
If Sentence.Contains(SplitString) Then
'Split all this into a List(Of String)...
With ListPossibleWords
.AddRange(Strings.Split(Sentence, SplitString.ToCharArray))
.RemoveAll(Function(s As String) As Boolean
Return s.Equals(SplitString)
End Function)
End With
'Do we have a list now?
If ListPossibleWords.Count >= Position Then ReturnWord = ListPossibleWords.Item(Position - 1)
End If
End If
Return ReturnWord
Catch ex As Exception
Return ReturnWord
End Try
End Function
The following might do what you want.
Module VBModule
Sub Main()
Dim sSearchIn As String = "Football ... Basketball ... Tennis ... Golf"
Dim sSearchFor As String = " ... "
Dim lItemPosition As Long = 3
Dim lSkipLen As Long = sSearchFor.Length
Dim lIndex As Long
Dim sTemp as String
Dim i As Long
' Mid is one-based, IndexOf is zero-based
sTemp = sSearchIn
For lIndex = 1 To lItemPosition - 1
sTemp = Mid (sTemp, sTemp.IndexOf(sSearchFor) + 1 + lSkipLen)
Next lIndex
i = sTemp.IndexOf(sSearchFor)
If (i > 0) Then
Console.WriteLine(Left (sTemp, i))
Else
Console.WriteLine(sTemp)
End If
End Sub
End Module
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
I'm hoping to improve the performance of the below as well as return the GUID of each user.
I've converted and modified the code found here for searching through groups recursively to get all the members and their details and adding them to a class collection. However I also need to capture the user's managers details so I'm calling the AD twice for each user. This doesn't seem efficient as many of the users will have the same manager. It would seem logical to get the distinct manager details from the collection class and call only these, then replace them wherever they occur in the collection. I don't know the best way to do this however - still fairly new to all this ;)
I'd also like to be able to get the user's GUID, I've tried accessing it directly as a property of the collection, but it doesn't return anything.
Here's my code, I'd really appreciate any comments/suggestions :) - or any bad habits I have in general pointing out! ;)
I'm using vs2005 and .Net 2.0
Public Class ADCLass
''' <summary>
''' Calls recursive function to return users in group
''' </summary>
''' <param name="DistListAlias">CN for the Group</param>
''' <returns>Collection of class holding user details</returns>
''' <remarks></remarks>
Public Function GetDistListUsers(ByVal DistListAlias As String) As Collection(Of ADMembers)
Dim path As String = "LDAP://DC=systems,DC=Private"
Dim filter As String
Dim filterFormat As String = "(cn={0})"
Dim sAMAccountFilter As String
filter = String.Format(filterFormat, DistListAlias)
Dim properties As PropertyCollection = GetPropertiesForEntry(path, filter)
sAMAccountFilter = "(|(ObjectClass=Group)(objectCategory=user))"
Dim groupMembers As Collection(Of ADMembers) = New Collection(Of ADMembers)
If Not IsNothing(properties) Then
Dim sAMAccountTypes As Collection(Of Integer) = New Collection(Of Integer)
groupMembers = GetUsersInGroup(properties, groupMembers, sAMAccountFilter)
End If
Return groupMembers
End Function
#Region "GetUsersInGroup"
''' <summary>
''' Recursive function to list all users in group and sub group
''' Returns the sAMAccountName for the Managers
''' </summary>
''' <param name="Properties">Group Properties</param>
''' <param name="groupMembers">Collection fo Users</param>
''' <param name="filter"></param>
''' <returns>Collection of class holding user details</returns>
''' <remarks></remarks>
Private Function GetUsersInGroup(ByVal Properties As PropertyCollection, ByVal groupMembers As Collection(Of ADMembers), ByVal filter As String)
Dim pathFormat As String = "LDAP://{0}"
Dim memberIdx As String = "member"
Dim sAMAccountNameIdx As String = "sAMAccountName"
Dim sAMAccountTypeIdx As String = "sAMAccountType"
Dim personnelNumberIdx As String = "extensionAttribute4"
Dim TelNo As String
Dim prop As Object
Dim managerID As String
Dim manColl As PropertyCollection
If Not IsNothing(Properties(memberIdx)) Then
'Loop through found Members
For Each prop In Properties(memberIdx)
Dim distinguishedName As String = prop.ToString
Dim path As String = String.Format(pathFormat, distinguishedName)
Dim childProperties As PropertyCollection = GetPropertiesForEntry(path, filter)
If Not IsNothing(childProperties) Then
'Check that this is a user
If childProperties(sAMAccountTypeIdx).Value = 805306368 Then
'GetManager ID
managerID = childProperties("manager").Value.ToString
manColl = GetPropertiesForEntry(String.Format(pathFormat, managerID), filter)
managerID = manColl(sAMAccountNameIdx).Value.ToString
'Get Phone Number, if telephone number is null, check mobile, if null
'return ""
If Not IsNothing(childProperties("telephoneNumber").Value) Then
TelNo = childProperties("telephoneNumber").Value.ToString
Else
If Not IsNothing(childProperties("mobile").Value) Then
TelNo = childProperties("mobile").Value.ToString
Else
TelNo = ""
End If
End If
'Add the Properties to the class collection
groupMembers.Add(New ADMembers(childProperties(sAMAccountNameIdx).Value.ToString, _
childProperties("cn").Value.ToString, _
managerID, _
childProperties("Title").Value.ToString, _
TelNo, _
childProperties("mail").Value.ToString))
Else
'Found a group - recurse
GetUsersInGroup(childProperties, groupMembers, filter)
End If
End If
Next
End If
Return groupMembers
End Function
#End Region
#Region "GetPropertiesForEntry"
''' <summary>
''' Gets properties for given user in AD
''' </summary>
''' <param name="path">Distinguished AD name</param>
''' <param name="filter"></param>
''' <returns>Property collection for given user</returns>
''' <remarks></remarks>
Private Function GetPropertiesForEntry(ByVal path As String, ByVal filter As String) As PropertyCollection
Dim rootEntry As New DirectoryEntry(path)
Dim searcher As New DirectorySearcher(rootEntry)
With searcher
.Filter = filter
.PageSize = 5
.ServerTimeLimit = New TimeSpan(0, 0, 30)
.ClientTimeout = New TimeSpan(0, 10, 0)
End With
Dim result As SearchResult = searcher.FindOne
Return result.GetDirectoryEntry.Properties
End Function
#End Region
End Class
Code I am using as per JPBlancs's suggestion, whilst this works, it is much slower than my original, am I implementing it incorreclty?
Public Sub GetPropertiesForEntry()
Dim rootEntry As New DirectoryEntry("LDAP://DC=d1,DC=d2")
Dim searcher As New DirectorySearcher(rootEntry)
With searcher
.Filter = "(&(memberof:1.2.840.113556.1.4.1941:=CN=grp1,OU=Messaging Groups,OU=Groups,DC=d1,DC=d2)(objectCategory=user))"
.SearchScope = SearchScope.Subtree
.PropertiesToLoad.Add("cn")
.PageSize = 100
.ServerTimeLimit = New TimeSpan(0, 0, 30)
.ClientTimeout = New TimeSpan(0, 10, 0)
End With
Dim results As SearchResultCollection = searcher.FindAll()
For Each result As SearchResult In results
Debug.Print(result.Properties("cn").Item(0).ToString)
Next
End Sub
Can you have a look to Finding users that are members of two active directory groups. You'll find a method using LDAP_MATCHING_RULE_IN_CHAIN to collect recursively users from a group in one query.
As far as th GUID is concerned don't forget list the attribute you want the query to return. Be careful, as far as I remember the GUID will return in an INT array.
dsLookFor.PropertiesToLoad.Add("objectGUID")
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
I have splitted comma separated values in an string array, something like this
str[0] ="210"
str[1] ="abc.pdf"
str[2] = "211"
str[3] = "xyz.docx"
and so on. Please note 0,2,4,6,8 [even positions] are having number and odd positions are having string.
I am having a class Attachmodel
Public Class AttachmentModel
Private _attachmentID As Integer = 0
Private _attachmentPath As String = ""
''' <summary>
''' Get Set Attachment ID
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property AttachmentID() As Integer
Get
Return _attachmentID
End Get
Set(ByVal value As Integer)
_attachmentID = value
End Set
End Property
''' <summary>
''' Get Set Attachment Path
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property AttachmentPath() As String
Get
Return _attachmentPath
End Get
Set(ByVal value As String)
_attachmentPath = value
End Set
End Property
End Class
In the above i want to set the values and bind it to the grid, using List
I want to bind CSV string with listbox programmatically
Private Sub BindAttachmentsToListBox(ByVal collectionData As String)
Dim arrayString As String()
Dim separator As String() = {",", "\n", " "}
Dim attachmentList As New List(Of AttachmentModel)
arrayString = collectionData.ToString().Split(separator, StringSplitOptions.RemoveEmptyEntries)
For i As Integer = 0 To arrayString.Length - 1
Dim attachments As New AttachmentModel()
attachments.AttachmentID = Integer.Parse(arrayString(i).ToString().Trim())
attachments.AttachmentPath = arrayString(i + 1).ToString.Trim()
attachmentList.Add(attachments)
i = i + 1
Next
lbAttachments.DataSource = attachmentList
lbAttachments.DisplayMember = "AttachmentPath"
lbAttachments.ValueMember = "AttachmentID"
End Sub