Archive: Pass Daialog - problem with serial.txt


Pass Daialog - problem with serial.txt
  I use this code to create new install program with serial window. I read many topic on the forum and in the site wiki and don't know how (i'm not programmer) must create file with serials to compare values (install program and serial.txt). Please help me :)

Name    "Serial"

>OutFile "Serial.exe"

>## Include headers
>!include MUI.nsh
>!include LogicLib.nsh

>## Pages
>!insertmacro MUI_PAGE_WELCOME
Page custom SerialPageShow SerialPageLeave
>;!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentsPageShow
>!insertmacro MUI_PAGE_COMPONENTS
>!insertmacro MUI_PAGE_INSTFILES

>## Languages
>!insertmacro MUI_LANGUAGE English

>## Displays the serial dialog
>Function SerialPageShow

>!insertmacro MUI_HEADER_TEXT "Enter Serial Code" "Enter the software serial code to continue."

>PassDialog::Dialog Serial
>/HEADINGTEXT 'Please enter the serial code located on the software CD case...'
>/CENTER
>/BOXDASH 12 70 4 ''
>/BOXDASH 92 70 4 ''
>/BOXDASH 172 70 4 ''
>/BOXDASH 252 70 4 ''
>/BOX 332 70 4 ''

>Pop $R0 # success, back, cancel or error

>FunctionEnd

>## Validate serial numbers
>Function SerialPageLeave

## Pop values from stack
Pop $R0
Pop $R1
Pop $R2
Pop $R3
Pop $R4

Banner
::show "Please Wait....Your Serial Number is Validating..."

## A bit of validation

>;StrCpy '$5' '$R0-$R1-$R2-$R3-$R4'
>StrCpy '$5' '$R0-$R1-$R2-$R3-$R4$\r$\n'
>StrCpy $6 0

Loop:
>IntOp $6 $6 + 1
StrCmp$6 500 Bad ;1 more than the # serials in file
>Push $6 ;line number to read from
File/oname=$PLUGINSDIRserial.txt "c:\serial.txt"
>Push "$PLUGINSDIR\serial.txt" ;text file to read
Call ReadFileLine
Pop$0 ;output string (read from file.txt)
>StrCmp $0 $5 Good
Goto Loop

Bad:
>Banner::destroy
MessageBox MB_OK|MB_ICONEXCLAMATION "The entered username or password is incorrect!"
>Delete "$PLUGINSDIR\serial.txt"
>Abort

Good:
>Delete "$PLUGINSDIR\serial.txt"
>FunctionEnd

>Function ReadFileLine
Exch$0 ;file
Exch
Exch$1 ;line number
Push$2
Push$3

FileOpen$2 $0 r
StrCpy$3 0
Loop:
>IntOp $3 $3 + 1
ClearErrors
FileRead$2 $0
IfErrors+2
StrCmp$3 $1 0 loop
FileClose$2

Pop$3
Pop$2
Pop$1
Exch$0

FunctionEnd

>## Just a dummy section
>Section 'A section'
>SectionEnd
>

So maybe someone can tell me what plugin and how I must use to do this. Please help me guys :)


Could you give a clear description of what you need your serial page to do?


When the serial page is display user must input serial code (he must buy a serial code before) to continue installation. I want integrate more than one serial in the installer but don't know how.


But what does the page need to *do*? How do you want it to look, how do you want it to behave? If all you need is a field to enter a serial code, simply create a custom page with nsDialogs that has two text fields. There's an excellent tutorial for that in the nsDialogs readme:
http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html


This page must compare code what user write with code enter in the file. I;m not programmer so i ask people who know something about this. I have script where i can put one serial to compare but i need more. I want ask if is possible and can somebody help me create this :)


So your idea is to have a list of valid keys and compare entered user's key against this list?
This may work but I think this is really risky - because you need to store your list of keys in installer (serials.txt), then unpack it to some directory (Temp) read the file (line by line) and do the comparison.

Every user can simply unpack your installer, grab key from the file and use it in the installer!!!

Maybe you could write your own plug-in (only C/C++ because C# plug-ins can decompiled easily) which would hold everything inside and it will do whole comparison for you.


Maybe is really risky but I don't programmer who know how create plugin. I never use language c/c++.


If it's really not important for you to be safe, simply do this:
- create custom page with nsDialogs (see nsDialogs tutorial I linked)
- add two text fields
- In the page's leave function, do


$serial1_HWND $serial1

>${NSD_GetText} $serial2_HWND $serial2
>${If} $serial1 == ${YourSerial1a}
${
OrIf} $serial1 == ${YourSerial1b}
>etc...
StrCpy $serial1valid = yes
>${Else}
StrCpy $serial1valid = no
>${EndIf}
${If}$serial2 == ${YourSerial2a}
${OrIf} $serial2 == ${YourSerial2b}
>etc...
StrCpy $serial2valid 'yes'
>${Else}
StrCpy $serial1valid 'no'
>${EndIf}

${If}$serial1valid != yes
>${OrIf} $serial2valid != yes
MessageBox MB_OK "Invalid serial(s)!"
abort
>${EndIf}

It is still difficult ....


Have you followed the tutorial in the nsDialogs readme?


Yes I read and try do something but for me is not easy

## Pages

>!insertmacro MUI_PAGE_WELCOME
Page custom SerialPageShow SerialPageLeave
>;!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentsPageShow
>!insertmacro MUI_PAGE_COMPONENTS
>!insertmacro MUI_PAGE_INSTFILES

>## Languages
>!insertmacro MUI_LANGUAGE English

>Var serial1
>Var serial2
>Var serial1valid
>Var serial2valid
>var serial1_HWND

>## Displays the serial dialog
>Function SerialPageShow

>!insertmacro MUI_HEADER_TEXT "Enter Serial Code" "Enter the software serial code to continue."


PassDialog::Dialog Serial

/HEADINGTEXT 'Please enter the serial code'
/CENTER
/BOX 152 70 5 ''
Pop $serial1_HWND

!define YourSerial1a "12345"
!define YourSerial2a "12346"



>nsDialogs::Show


FunctionEnd
>

You are mixing nsDialogs and PassDialog. They are different plugins, don't use them together on one installer page. If you want to use passdialog, follow the example in PassDialog.zip\Examples\PassDialog\Serial.nsi .


I try used PassDialog but don't work (i can only put one serial) In nsDialogs i create custom page but I don't what code i must use to work with your scirpt


nsDialogs::Create 1018

Pop $serial1_HWND


${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $serial1


!define YourSerial1a "12345"
!define YourSerial2a "12346"



>nsDialogs::Show
>

no progress... please help ;/


Originally posted by Manchut
no progress... please help ;/

SerialPageShow


InitPluginsDir
nsDialogs
::Create 1018

${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $give_HWND

>${NSD_LB_GetSelection} $give_HWND $serial1_HWND

>${NSD_SetText} $serial1 ${12345}

>nsDialogs::Show

FunctionEnd
>

Function SerialPageShow
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}

${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $serial1_HWND
nsDialogs::Show
FunctionEnd

Function SerialPageLeave
${NSD_GetText} $serial1_HWND $serial1
${If} $serial1 != "12345"
MessageBox MB_OK "Invalid serial!"
abort
${EndIf}
FunctionEnd


You could have figured this out if you had studied the tutorial. It is extremely clear. Perhaps you need to find someone to translate it into your native language?


Maybe is clear but my English is not perfect so i don't understand all words. I use goggle translate but you know... This script work only with one serial, don't be angry but how use your code what you write before?


$serial1_HWND $serial1

>${NSD_GetText} $serial2_HWND $serial2
>${If} $serial1 == ${YourSerial1a}
${
OrIf} $serial1 == ${YourSerial1b}
>etc...
StrCpy $serial1valid = yes
>${Else}
StrCpy $serial1valid = no
>${EndIf}
${If}$serial2 == ${YourSerial2a}
${OrIf} $serial2 == ${YourSerial2b}
>etc...
StrCpy $serial2valid 'yes'
>${Else}
StrCpy $serial1valid 'no'
>${EndIf}

${If}$serial1valid != yes
>${OrIf} $serial2valid != yes
MessageBox MB_OK "Invalid serial(s)!"
abort
>${EndIf}

Ok i can´t read only longer to this thread...

@MSG: He doesn´t need the code for the custom page only. He need the whole concept for the serial stuff. Code generating & encrypting too.

@Manchut: How do you generate your serials? I ask because the idea of storing (all) serials in a textfile is bad. Because of 2 things:
1. How many serials you will store? 100, 1000? What if you have 1001 Users? Will you provide the first serial twice?
2. The textfile will be unpacked to $pluginsdir during runtime. So the complete textfile with ALL serials in it will be found in the users %temp% folder. Readable for everyone. So why obtain a serial from you (for money) when i can get ALL valid serials for free?

So you have to find another solution. Maybe the Registration Plugin in the NSIS plugin section will help you.

But this will not save your content in the installer to get unpacked anyway. Because you can unpack the content of the installer simply with 7-Zip.
The better way is to integrate the serial stuff in your application you wat to provide and not in the installer...

just my 2 cent


Function SerialPageLeave
StrCpy $n 1
loop:
IntCmp $n 1000 0 0 done
${NSD_GetText} $serial_HWND "serial$n"
StrCmp "serial$n" "12345" match
IntOp $n $n + 1
goto loop
done:
MessageBox MB_OK "Invalid serial!"
abort
match:
FunctionEnd

Not sure this code helps at all in your case, but you should try with a loop to get away from all those ${OrIf} conditions.


; your 1 password for everyone is "happy"
; use an md5 generator to encrypt happy
; md5 = 56ab24c15b72a457069c5ea42fcfc640

Var KEY ; happy
ReserveFile "${NSISDIR}\Plugins\md5dll.dll"

; now generate 1000 serials

Function SerialPageLeave
StrCpy $KEY "56ab24c15b72a457069c5ea42fcfc640"
StrCpy $R0 1
loop:
IntCmp $R0 1000 0 0 done
${NSD_GetText} $serial_HWND $R1
md5dll::GetMD5String "$KEY$R0" ; generate 1000 times
Pop $R3
StrCmp $R1 $R3 match
IntOp $R0 $R0 + 1
goto loop
done:
MessageBox MB_OK "Invalid serial!"
abort
match:
FunctionEnd

; your 1000 serials are all different
; to decrypt them you need the key
; you can create a private list with the generated serials, but don't copy it to the $pluginsdir


${NSD_GetText} $serial_HWND $R1 -- doesn't need to be in the loop. It can come before.

My mistake.

If you already have a list of serials, ie. 12345, 12346, 12347, here is another option:

Var serial

!macro serials num
StrCpy $serial "1234${num}"
!macroend

Function SerialPageLeave
StrCpy $R0 5
${NSD_GetText} $serial_HWND $R1
loop:
IntCmp $R0 7 0 0 done
!insertmacro serials $R0
StrCmp $serial $R1 match
IntOp $R0 $R0 + 1
goto loop
done:
MessageBox MB_OK "Invalid serial!"
abort
match:
FunctionEnd


Highcoder
1. Last time this patch download about 1000 people. But serials can be repeat.
2. I want use this install program for patch so I thing that many users buy this patch and don't be search temp file to find this file (cash going for website not for me). Registration Plugin is not free and I don't have money to buy ;/


Bnicer thanks so much for codes :) I have question.

When i try generate your code i have error

1. "!insertmacro: macro "serials_num" requires 0 parameter(s), passed 1!
Error in script "C:\Users\Thom\Desktop\test.txt" on line 123 -- aborting creation process"
!insertmacro serials $R0

2. With code md5 i can't understand this. Where I find this list, i must use ReserveFile to add this file?

Thanks for help and patient;)


Originally posted by Manchut
Maybe is clear but my English is not perfect so i don't understand all words. I use goggle translate but you know... This script work only with one serial, don't be angry but how use your code what you write before?
Don't worry, I won't get angry. To get your custom page to accept two serials, simply add a second textbox to the page function:
Function SerialPageShow
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}

${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $serial1_HWND
${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $serial2_HWND

nsDialogs::Show
FunctionEnd

That's how nsDialogs works: You add components by adding ${NSD_Create...} macros before you nsDialogs::Show the page.

Err oops, the coordinates for the two password fields should of course not be the same:
${NSD_CreatePassword} 0 10% 50% 8% ""
Pop $serial1_HWND
${NSD_CreatePassword} 0 20% 50% 8% ""
Pop $serial2_HWND


But this code create two different window so is not good for me... :(


Then what exactly do you need?


I have custom page with place to write password. But still have problem with script. I want put in the install program 100 serials (I can do this manually) who are verified by script. Your script work great but only for one serial, script what put Bnicer for me still don't understandable...


${OrIf} $serial1 == ${YourSerial1b}
^-- that line is where you add more possible serial codes.

Once again, keep in mind that this method is NOT secure at all. It will be very easy to extract all possible serial codes from your installer. (And HighCoder also mentioned that it will be easy to extract your program files from the installer, even if the user doesn't have a serial key.)

Since you are not very experienced with programming, you should find/hire someone who is experienced, so you can get a more secure solution.


http://nsis.sourceforge.net/MD5_plugin.

Generating a list of serials is easy.

StrCpy $R0 1
loop:
IntCmp $R0 100 0 0 done
md5dll::GetMD5String "$KEY$R0" ; generate 100 times
Pop $R3
DetailPrint "Serial$R0 $R3"
IntOp $R0 $R0 + 1
goto loop
done:

Then copy the text to the clipboard and save the list:

Serial1 41da99a57f72e811faca6dfaaa403a3c
Serial2 d0dccc680767fb0acb2f5df0457c2148
Serial3 2bbf3c130706078ef96ce561841b9a93

For checking user input on your password page, the method is almost the same.

Function SerialPageLeave
; only you know that the key is "happy"
StrCpy $KEY "56ab24c15b72a457069c5ea42fcfc640"
StrCpy $R0 1
${NSD_GetText} $serial_HWND $R1
loop:
IntCmp $R0 100 0 0 done
md5dll::GetMD5String "$KEY$R0" ; generate 100 times
Pop $R3
StrCmp $R1 $R3 match
IntOp $R0 $R0 + 1
goto loop
done:
MessageBox MB_OK "Invalid serial!"
abort
match:
FunctionEnd

=======

You can make an md5 hash as secure as you like by encrypting it again and again with different keys.

Take 56ab24c15b72a457069c5ea42fcfc640 (happy), for instance, and calculate an md5 hash for 56ab24c15b72a457069c5ea42fcfc640+sad. The resulting hash will have two levels of encryption, and should be almost impossible to crack.

Unless somebody read this thread. Therefore always add a few twists and turns.

=======

MSG is right too, somebody can extract the serials from your installer, and the method for generating the serials.


Ok now i better understand all. But when i put and compilation this


Name "MD5dll Example"

>OutFile "keys.exe"
>ShowInstDetails show

Section
StrCpy $R0 1
loop:
>IntCmp $R0 100 0 0 done
md5dll
::GetMD5String "$KEY$R0" ; generate 100 times
Pop $R3
DetailPrint "Serial$R0 $R3"
>goto loop
done:
>SectionEND
>
and install program don't work. I use windows 8 maybe this is problem?

ReserveFile "${NSISDIR}\Plugins\md5dll.dll"
Var KEY

Section
StrCpy $KEY "56ab24c15b72a457069c5ea42fcfc640"
StrCpy $R0 1
loop:
IntCmp $R0 100 0 0 done
md5dll::GetMD5String "$KEY$R0" ; generate 100 times
Pop $R3
DetailPrint "Serial$R0 $R3"
IntOp $R0 $R0 + 1
goto loop
done:
SectionEnd

That works on Windows 7.


Great, now work. Thanks so much for help :))