Subversion Repositories Games.Chess Giants

Rev

Rev 88 | Rev 140 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
// dialog_registration.cpp
2
 
3
#include "../common.h"
4
 
5
 
6
// dialog template
7
#define THIS_DIALOG DIALOG_REGISTER
8
 
9
 
83 pmbaty 10
// global variables used in this module only
11
static wchar_t candidate_email[128] = L"";
12
static unsigned __int32 candidate_code = 0; // 32 bits
13
 
14
 
14 pmbaty 15
// prototypes of local functions
16
static int CALLBACK DialogProc_ThisDialog (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam);
83 pmbaty 17
static unsigned __int32 RetrieveActivationCode (wchar_t *candidate_email, wchar_t **failure_reason);
88 pmbaty 18
static int recv_with_timeout (int socket_id, float timeout_in_seconds, char *outbuf, size_t outbuf_size, int flags);
14 pmbaty 19
 
20
 
21
void DialogBox_Registration (void)
22
{
23
   // helper function to fire up the modal dialog box
24
 
25
   // display the dialog box (set the parent to be the desktop)
26
   DialogBox (hAppInstance, MAKEINTRESOURCE (THIS_DIALOG), NULL, DialogProc_ThisDialog);
27
 
28
   return; // finished processing this dialog
29
}
30
 
31
 
32
static int CALLBACK DialogProc_ThisDialog (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
33
{
34
   // message handler for the dialog box
35
 
83 pmbaty 36
   static wchar_t temp_string[1024];
14 pmbaty 37
 
38
   unsigned short wParam_hiword;
39
   unsigned short wParam_loword;
83 pmbaty 40
   wchar_t *failure_reason;
41
   int write_index;
14 pmbaty 42
   int read_index;
43
   int length;
44
 
45
   // filter out the commonly used message values
46
   wParam_hiword = HIWORD (wParam);
47
   wParam_loword = LOWORD (wParam);
48
 
49
   // have we just fired up this window ?
50
   if (message == WM_INITDIALOG)
51
   {
52
      // center the window
53
      CenterWindow (hWnd, hMainWnd);
54
 
55
      // set dialog icons (small one for title bar & big one for task manager)
56
      SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon (hAppInstance, MAKEINTRESOURCE (ICON_MAIN)));
57
      SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) LoadIcon (hAppInstance, MAKEINTRESOURCE (ICON_MAIN)));
58
 
59
      // set window title and control texts
60
      SetWindowText (hWnd, LOCALIZE (L"Registration_Title"));
61
 
62
      // set the static texts
63
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_QUESTION), LOCALIZE (L"Registration_Question"));
64
      SetWindowText (GetDlgItem (hWnd, BUTTON_DONATE), LOCALIZE (L"Registration_Donate"));
65
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_NOPAYPAL), LOCALIZE (L"Registration_NoPayPal"));
66
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_INSTRUCTIONS), LOCALIZE (L"Registration_Instructions"));
23 pmbaty 67
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_CODENOTRECEIVED), LOCALIZE (L"Registration_CodeNotReceived"));
14 pmbaty 68
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_EMAILADDRESS), LOCALIZE (L"Registration_EmailAddress"));
83 pmbaty 69
      if (options.registration.user_email[0] != 0)
70
         SetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, options.registration.user_email);
71
      else
72
         SetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, L"your@email.here");
14 pmbaty 73
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_ACTIVATIONCODE), LOCALIZE (L"Registration_ActivationCode"));
74
      //SetDlgItemInt (hWnd, EDITBOX_REGISTRATION_ACTIVATIONCODE, options.registration.activation_code, false);
75
      SetWindowText (GetDlgItem (hWnd, BUTTON_VALIDATECODE), LOCALIZE (L"Registration_ValidateCode"));
76
      Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_STATUSBAR), LOCALIZE (L"Registration_StatusBar"));
77
 
78
      // set focus to the first settable item
79
      SendMessage (GetDlgItem (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS), EM_SETSEL, 0, -1); // select all text
80
      SetFocus (GetDlgItem (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS));
81
 
82
      // convert the "no paypal" and the status bar message to hyperlinks
83
      ConvertStaticToHyperlink (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_NOPAYPAL));
23 pmbaty 84
      ConvertStaticToHyperlink (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_CODENOTRECEIVED));
14 pmbaty 85
      ConvertStaticToHyperlink (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_STATUSBAR));
86
   }
87
 
88
   // else did we click the close button on the title bar ?
89
   else if (message == WM_CLOSE)
90
      EndDialog (hWnd, 0); // close the dialog box
91
 
92
   // else did we take action on one of the controls ?
93
   else if (message == WM_COMMAND)
94
   {
95
      // did we cancel the dialog box ? (IDCANCEL is a system-wide dialog box handler value, that catches the ESC key)
96
      if (wParam_loword == IDCANCEL)
97
         EndDialog (hWnd, 0); // close the dialog box
98
 
21 pmbaty 99
      // else did the user enter something in the edit boxes ?
100
      else if (wParam_hiword == EN_CHANGE)
101
      {
83 pmbaty 102
         // enable the validation button only if the PayPal email field has data
21 pmbaty 103
         GetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, candidate_email, WCHAR_SIZEOF (candidate_email));
104
 
83 pmbaty 105
         // strip spaces and unprintable characters from candidate email, and bring it lowercase
14 pmbaty 106
         length = wcslen (candidate_email);
107
         write_index = 0;
108
         for (read_index = 0; read_index < length; read_index++)
19 pmbaty 109
            if (!iswspace (candidate_email[read_index]))
14 pmbaty 110
            {
83 pmbaty 111
               candidate_email[write_index] = tolower (candidate_email[read_index]); // force lowercase
112
               write_index++; // keep only valid signs and discard spaces
14 pmbaty 113
            }
114
         candidate_email[write_index] = 0; // ensure string is correctly terminated
115
 
83 pmbaty 116
         EnableWindow (GetDlgItem (hWnd, BUTTON_VALIDATECODE), ((candidate_email[0] != 0) && (wcslen (candidate_email) > 5) && (wcsncmp (candidate_email, L"your@email.", 11) != 0)
117
                                                                && (wcschr (candidate_email, L'@') != NULL) && (wcschr (candidate_email, L'.') != NULL)));
118
      }
14 pmbaty 119
 
83 pmbaty 120
      // else was it the validation button ?
121
      else if (wParam_loword == BUTTON_VALIDATECODE)
122
      {
123
         // query the remote server for the code associated with this email. If it fails, ask why.
124
         candidate_code = RetrieveActivationCode (candidate_email, &failure_reason);
14 pmbaty 125
 
83 pmbaty 126
         // was there a problem retrieving the code ?
127
         if ((failure_reason != NULL) && (failure_reason[0] != 0))
128
            MessageBox (hWnd, failure_reason, PROGRAM_NAME, MB_ICONERROR | MB_OK); // registration failed. Display an error and DON'T exit the program
129
 
130
         // else is the retrieved data correct ?
14 pmbaty 131
         else if (IsRegistrationCorrect (candidate_email, candidate_code))
132
         {
83 pmbaty 133
            // if so, save activation email and activation code
134
            wcscpy_s (options.registration.user_email, WCHAR_SIZEOF (options.registration.user_email), candidate_email);
14 pmbaty 135
            options.registration.activation_code = candidate_code;
136
            MessageBox (hWnd, LOCALIZE (L"Registration_ThankYou"), PROGRAM_NAME, MB_ICONINFORMATION | MB_OK);
137
            EndDialog (hWnd, 0); // then display a thank you dialog box and exit the program
138
         }
139
 
140
         // else the supplied data is wrong
141
         else
142
         {
83 pmbaty 143
            swprintf_s (temp_string, WCHAR_SIZEOF (temp_string), LOCALIZE (L"Registration_Error"), AUTHOR_EMAIL);
144
            MessageBox (hWnd, temp_string, PROGRAM_NAME, MB_ICONERROR | MB_OK); // wrong activation. Display an error and DON'T exit the program
14 pmbaty 145
         }
146
      }
147
 
148
      // else was it the PayPal button ?
149
      else if (wParam_loword == BUTTON_DONATE)
89 pmbaty 150
      {
151
         if (wcscmp (languages[language_id].name, L"French") == 0)
152
            ShellExecute (NULL, L"open", PAYPAL_URL_FR, NULL, NULL, SW_MAXIMIZE); // open PayPal in French in the default browser, maximized
153
         else
154
            ShellExecute (NULL, L"open", PAYPAL_URL_XX, NULL, NULL, SW_MAXIMIZE); // open PayPal in English (default) the default browser, maximized
155
      }
14 pmbaty 156
 
157
      // else was it the "no PayPal" hyperlink ?
158
      else if (wParam_loword == STATICTEXT_REGISTRATION_NOPAYPAL)
23 pmbaty 159
         ShellExecute (NULL, L"open", NOPAYPAL_URL, NULL, NULL, SW_MAXIMIZE); // open the bank account page in the default browser, maximized
14 pmbaty 160
 
161
      // else was it the status bar hyperlink ?
162
      else if (wParam_loword == STATICTEXT_REGISTRATION_STATUSBAR)
23 pmbaty 163
         ShellExecute (NULL, L"open", PROGRAM_URL, NULL, NULL, SW_MAXIMIZE); // open the main page in the default browser, maximized
14 pmbaty 164
   }
165
 
166
   // call the default dialog message processing function to keep things going
167
   return (false);
168
}
83 pmbaty 169
 
170
 
171
static unsigned __int32 RetrieveActivationCode (wchar_t *candidate_email, wchar_t **failure_reason)
172
{
173
   // this function queries the remote server for registration status. If OK, the received code is returned.
174
   // On error, 0 is returned and error_string points to the cause of the error (as reported by the server)
175
   // which is stored in a static buffer in this very function.
176
 
177
   static char http_buffer[1024]; // used both for request and reply
178
   static char ascii_email[128];
179
 
180
   struct sockaddr_in service;
181
   struct hostent *hostinfo;
182
   char *data_start;
183
   WSADATA wsa_data;
184
   int write_index;
185
   int read_index;
186
   int length;
187
   SOCKET s;
188
 
189
   // initialize WinSock
190
   if (WSAStartup (MAKEWORD (2, 2), &wsa_data) != 0)
191
   {
192
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
193
      return (0); // couldn't initialize WinSock, return an error condition
194
   }
195
 
196
   // get our distribution server's IP address from the host name
197
   hostinfo = gethostbyname ("pmbaty.com");
198
   if (hostinfo == NULL)
199
   {
200
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
201
      return (0); // couldn't resolve hostname, return an error condition
202
   }
203
 
204
   // fill in the sockaddr server structure with the server hostinfo data
205
   service.sin_family = AF_INET;
206
   service.sin_addr.s_addr = inet_addr (inet_ntoa (*(struct in_addr *) hostinfo->h_addr_list[0]));
207
   service.sin_port = htons (80); // connect to webserver there (port 80)
208
 
209
   // create our socket
210
   if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
211
   {
212
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
213
      return (0); // couldn't create socket, return an error condition
214
   }
215
 
216
   // connect to the distributor's webserver using that socket
217
   if (connect (s, (struct sockaddr *) &service, sizeof (service)) == -1)
218
   {
219
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
220
      return (0); // unable to connect to webserver, return an error condition
221
   }
222
 
223
   // build the HTTP query and send it
224
   ConvertTo7BitASCII (ascii_email, sizeof (ascii_email), candidate_email);
225
   sprintf_s (http_buffer, sizeof (http_buffer),
226
      "GET /chess/whatsmycode.php?email=%s HTTP/1.1\r\n"
227
      "Host: pmbaty.com\r\n"
228
      "Connection: close\r\n"
229
      "\r\n", ascii_email);
230
   length = strlen (http_buffer);
231
   write_index = send (s, http_buffer, length, 0); // send the HTTP query
232
   if (write_index != length)
233
   {
234
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
235
      return (0); // unable to send HTTP query, return an error condition
236
   }
237
 
88 pmbaty 238
   // read the reply (10 seconds timeout)
239
   http_buffer[0] = 0;
240
   read_index = recv_with_timeout (s, 10.0f, http_buffer, sizeof (http_buffer), 0);
83 pmbaty 241
   if (read_index < 1)
242
   {
243
      *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
244
      return (0); // empty or erroneous HTTP reply, return an error condition
245
   }
246
 
247
   closesocket (s); // finished communicating, close TCP socket
248
   WSACleanup (); // and clean up WinSock
249
 
250
   // terminate recv buffer and see where the useful data starts
251
   http_buffer[read_index] = 0;
252
   //MessageBoxA (NULL, http_buffer, "HTTP response", MB_OK);
253
   if ((data_start = strstr (http_buffer, "Success=")) != NULL)
254
   {
255
      *failure_reason = L""; // no error, set an empty string as the failure reason
256
      return ((unsigned __int32) atoll (&data_start[strlen ("Success=")])); // and return the candidate code we got
257
   }
258
   else if ((data_start = strstr (http_buffer, "Error=")) != NULL)
259
   {
260
      data_start += strlen ("Error=");
261
      if (strchr (data_start, '\r') != NULL) *strchr (data_start, '\r') = 0;
262
      if (strchr (data_start, '\n') != NULL) *strchr (data_start, '\n') = 0;
263
      if      (_stricmp (data_start, "WrongEmail") == 0)         *failure_reason = LOCALIZE (L"Registration_WrongEmail");
264
      else if (_stricmp (data_start, "UnknownEmail") == 0)       *failure_reason = LOCALIZE (L"Registration_UnknownEmail");
265
      else if (_stricmp (data_start, "TooManyActivations") == 0) *failure_reason = LOCALIZE (L"Registration_TooManyActivations");;
88 pmbaty 266
      return (0); // server returned an error, return an error condition
83 pmbaty 267
   }
268
 
88 pmbaty 269
   *failure_reason = LOCALIZE (L"Registration_NetworkFailure"); // this should never happen
83 pmbaty 270
   return (0); // server returned an error, return an error condition
271
}
88 pmbaty 272
 
273
 
274
static int recv_with_timeout (int socket_id, float timeout_in_seconds, char *outbuf, size_t outbuf_size, int flags)
275
{
276
   unsigned long nonblocking_mode;
277
   unsigned long msec_start;
278
   float timediff;
279
   int total_size;
280
   int recv_size;
281
 
282
   // make socket non blocking
283
   nonblocking_mode = 1;
284
   ioctlsocket (socket_id, FIONBIO, &nonblocking_mode);
285
 
286
   // loop endlessly, noting the time at which we start
287
   msec_start = GetTickCount ();
288
   total_size = 0;
289
   for (;;)
290
   {
291
      // see how much time elapsed since the last time we received data
292
      timediff = (GetTickCount () - msec_start) / 1000.0f;
293
      if (timediff > timeout_in_seconds)
294
         break; // if we've waited long enough, give up
295
 
296
      // see if we have something to read from the socket
297
      recv_size = recv (socket_id, &outbuf[total_size], outbuf_size - total_size, flags);
298
      if (recv_size == 0)
299
         break; // on TCP disconnection, give up too
300
      else if (recv_size < 0)
301
      {
302
         Sleep (100); // if nothing was received then we want to wait a little before trying again, 0.1 seconds
303
         continue;
304
      }
305
 
306
      total_size += recv_size; // increase the received bytes count
307
      outbuf[total_size] = 0; // terminate outbuf ourselves
308
      if (total_size == outbuf_size)
309
         break; // if the output buffer is full, give up
310
      msec_start = GetTickCount (); // and remember when we last received data (i.e. now)
311
   }
312
 
313
   return (total_size); // and return the number of bytes received
314
}