Subversion Repositories Games.Chess Giants

Rev

Rev 147 | Rev 179 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // dialog_registration.cpp
  2.  
  3. #include "../common.h"
  4.  
  5.  
  6. // dialog template
  7. #define THIS_DIALOG DIALOG_REGISTER
  8.  
  9.  
  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.  
  15. // prototypes of local functions
  16. static int CALLBACK DialogProc_ThisDialog (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam);
  17. static unsigned __int32 RetrieveActivationCode (wchar_t *candidate_email, wchar_t **failure_reason);
  18.  
  19.  
  20. void DialogBox_Registration (void)
  21. {
  22.    // helper function to fire up the modal dialog box
  23.  
  24.    // display the dialog box (set the parent to be the desktop)
  25.    DialogBox (hAppInstance, MAKEINTRESOURCE (THIS_DIALOG), NULL, DialogProc_ThisDialog);
  26.  
  27.    return; // finished processing this dialog
  28. }
  29.  
  30.  
  31. static int CALLBACK DialogProc_ThisDialog (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
  32. {
  33.    // message handler for the dialog box
  34.  
  35.    static wchar_t temp_string[1024];
  36.  
  37.    unsigned short wParam_hiword;
  38.    unsigned short wParam_loword;
  39.    wchar_t *failure_reason;
  40.    int write_index;
  41.    int read_index;
  42.    int length;
  43.  
  44.    // filter out the commonly used message values
  45.    wParam_hiword = HIWORD (wParam);
  46.    wParam_loword = LOWORD (wParam);
  47.  
  48.    // have we just fired up this window ?
  49.    if (message == WM_INITDIALOG)
  50.    {
  51.       // center the window
  52.       CenterWindow (hWnd, hMainWnd);
  53.  
  54.       // set dialog icons (small one for title bar & big one for task manager)
  55.       SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon (hAppInstance, MAKEINTRESOURCE (ICON_MAIN)));
  56.       SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) LoadIcon (hAppInstance, MAKEINTRESOURCE (ICON_MAIN)));
  57.  
  58.       // set window title and control texts
  59.       SetWindowText (hWnd, LOCALIZE (L"Registration_Title"));
  60.  
  61.       // set the static texts
  62.       Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_QUESTION), LOCALIZE (L"Registration_Question"));
  63.       Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_INSTRUCTIONS), LOCALIZE (L"Registration_Instructions"));
  64.       // set email address font
  65.       SendMessage (GetDlgItem (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS), WM_SETFONT, (WPARAM) GetStockObject (SYSTEM_FONT), 0);
  66.       if (options.registration.user_email[0] != 0)
  67.          SetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, options.registration.user_email);
  68.       else
  69.          SetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, LOCALIZE (L"Registration_YourEmailHere"));
  70.       SetWindowText (GetDlgItem (hWnd, BUTTON_VALIDATECODE), LOCALIZE (L"Registration_ValidateCode"));
  71.       Static_SetText (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_STATUSBAR), LOCALIZE (L"Registration_StatusBar"));
  72.  
  73.       // set focus to the first settable item
  74.       SendMessage (GetDlgItem (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS), EM_SETSEL, 0, -1); // select all text
  75.       SetFocus (GetDlgItem (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS));
  76.  
  77.       // convert the Paypal bitmap and the status bar message to hyperlinks
  78.       ConvertStaticToHyperlink (GetDlgItem (hWnd, BUTTON_DONATE));
  79.       ConvertStaticToHyperlink (GetDlgItem (hWnd, STATICTEXT_REGISTRATION_STATUSBAR));
  80.    }
  81.  
  82.    // else did we click the close button on the title bar ?
  83.    else if (message == WM_CLOSE)
  84.       EndDialog (hWnd, 0); // close the dialog box
  85.  
  86.    // else did we take action on one of the controls ?
  87.    else if (message == WM_COMMAND)
  88.    {
  89.       // did we cancel the dialog box ? (IDCANCEL is a system-wide dialog box handler value, that catches the ESC key)
  90.       if (wParam_loword == IDCANCEL)
  91.          EndDialog (hWnd, 0); // close the dialog box
  92.  
  93.       // else did the user enter something in the edit boxes ?
  94.       else if (wParam_hiword == EN_CHANGE)
  95.       {
  96.          // enable the validation button only if the PayPal email field has data
  97.          GetDlgItemText (hWnd, EDITBOX_REGISTRATION_EMAILADDRESS, candidate_email, WCHAR_SIZEOF (candidate_email));
  98.  
  99.          // strip spaces and unprintable characters from candidate email, and bring it lowercase
  100.          length = wcslen (candidate_email);
  101.          write_index = 0;
  102.          for (read_index = 0; read_index < length; read_index++)
  103.             if (!iswspace (candidate_email[read_index]))
  104.             {
  105.                candidate_email[write_index] = tolower (candidate_email[read_index]); // force lowercase
  106.                write_index++; // keep only valid signs and discard spaces
  107.             }
  108.          candidate_email[write_index] = 0; // ensure string is correctly terminated
  109.  
  110.          EnableWindow (GetDlgItem (hWnd, BUTTON_VALIDATECODE), ((candidate_email[0] != 0) && (wcslen (candidate_email) > 5) && (wcscmp (candidate_email, LOCALIZE (L"Registration_YourEmailHere")) != 0)
  111.                                                                 && (wcschr (candidate_email, L'@') != NULL) && (wcschr (candidate_email, L'.') != NULL)));
  112.       }
  113.  
  114.       // else was it the validation button ?
  115.       else if (wParam_loword == BUTTON_VALIDATECODE)
  116.       {
  117.          // query the remote server for the code associated with this email. If it fails, ask why.
  118.          candidate_code = RetrieveActivationCode (candidate_email, &failure_reason);
  119.  
  120.          // was there a problem retrieving the code ?
  121.          if ((failure_reason != NULL) && (failure_reason[0] != 0))
  122.             MessageBox (hWnd, failure_reason, PROGRAM_NAME, MB_ICONERROR | MB_OK); // registration failed. Display an error and DON'T make the dialog box disappear
  123.  
  124.          // else is the retrieved data correct ?
  125.          else if (IsRegistrationCorrect (candidate_email, candidate_code))
  126.          {
  127.             // if so, save activation email and activation code
  128.             wcscpy_s (options.registration.user_email, WCHAR_SIZEOF (options.registration.user_email), candidate_email);
  129.             options.registration.activation_code = candidate_code;
  130.             MessageBox (hWnd, LOCALIZE (L"Registration_ThankYou"), PROGRAM_NAME, MB_ICONINFORMATION | MB_OK);
  131.             EndDialog (hWnd, 0); // then display a thank you dialog box and make the dialog box disappear
  132.          }
  133.  
  134.          // else the supplied data is wrong
  135.          else
  136.          {
  137.             swprintf_s (temp_string, WCHAR_SIZEOF (temp_string), LOCALIZE (L"Registration_Error"), AUTHOR_EMAIL);
  138.             MessageBox (hWnd, temp_string, PROGRAM_NAME, MB_ICONERROR | MB_OK); // wrong activation. Display an error and DON'T make the dialog box disappear
  139.          }
  140.       }
  141.  
  142.       // else was it the PayPal button ?
  143.       else if (wParam_loword == BUTTON_DONATE)
  144.       {
  145.          MessageBox (hWnd, LOCALIZE (L"Registration_DontForget"), PROGRAM_NAME, MB_ICONWARNING | MB_OK); // users need to be reminded that they MUST write their email in the activation form
  146.  
  147.          if (wcscmp (languages[language_id].name, L"French") == 0)
  148.             ShellExecute (NULL, L"open", PAYPAL_URL_FR, NULL, NULL, SW_MAXIMIZE); // open PayPal in French in the default browser, maximized
  149.          else
  150.             ShellExecute (NULL, L"open", PAYPAL_URL_XX, NULL, NULL, SW_MAXIMIZE); // open PayPal in English (default) the default browser, maximized
  151.       }
  152.  
  153.       // else was it the status bar hyperlink ?
  154.       else if (wParam_loword == STATICTEXT_REGISTRATION_STATUSBAR)
  155.          ShellExecute (NULL, L"open", PROGRAM_URL, NULL, NULL, SW_MAXIMIZE); // open the main page in the default browser, maximized
  156.    }
  157.  
  158.    // call the default dialog message processing function to keep things going
  159.    return (false);
  160. }
  161.  
  162.  
  163. static unsigned __int32 RetrieveActivationCode (wchar_t *candidate_email, wchar_t **failure_reason)
  164. {
  165.    // this function queries the remote server for registration status. If OK, the received code is returned.
  166.    // On error, 0 is returned and error_string points to the cause of the error (as reported by the server)
  167.    // which is stored in a static buffer in this very function.
  168.  
  169.    static char http_buffer[1024]; // used both for request and reply
  170.    static char ascii_email[128];
  171.  
  172.    struct sockaddr_in service;
  173.    struct hostent *hostinfo;
  174.    char *data_start;
  175.    int write_index;
  176.    int read_index;
  177.    int length;
  178.    SOCKET s;
  179.  
  180.    // initialize the network subsystem if required
  181.    if (!Network_Init ())
  182.    {
  183.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  184.       return (0); // couldn't initialize WinSock, return an error condition
  185.    }
  186.  
  187.    // get our distribution server's IP address from the host name
  188.    hostinfo = gethostbyname ("pmbaty.com");
  189.    if (hostinfo == NULL)
  190.    {
  191.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  192.       return (0); // couldn't resolve hostname, return an error condition
  193.    }
  194.  
  195.    // fill in the sockaddr server structure with the server hostinfo data
  196.    service.sin_family = AF_INET;
  197.    service.sin_addr.s_addr = inet_addr (inet_ntoa (*(struct in_addr *) hostinfo->h_addr_list[0]));
  198.    service.sin_port = htons (80); // connect to webserver there (port 80)
  199.  
  200.    // create our socket
  201.    if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
  202.    {
  203.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  204.       return (0); // couldn't create socket, return an error condition
  205.    }
  206.  
  207.    // connect to the distributor's webserver using that socket
  208.    if (connect (s, (struct sockaddr *) &service, sizeof (service)) == -1)
  209.    {
  210.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  211.       return (0); // unable to connect to webserver, return an error condition
  212.    }
  213.  
  214.    // build the HTTP query and send it
  215.    ConvertTo7BitASCII (ascii_email, sizeof (ascii_email), candidate_email);
  216.    sprintf_s (http_buffer, sizeof (http_buffer),
  217.       "GET /chess/whatsmycode.php?email=%s HTTP/1.1\r\n"
  218.       "Host: pmbaty.com\r\n"
  219.       "Connection: close\r\n"
  220.       "\r\n", ascii_email);
  221.    length = strlen (http_buffer);
  222.    write_index = send (s, http_buffer, length, 0); // send the HTTP query
  223.    if (write_index != length)
  224.    {
  225.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  226.       return (0); // unable to send HTTP query, return an error condition
  227.    }
  228.  
  229.    // read the reply (10 seconds timeout)
  230.    http_buffer[0] = 0;
  231.    read_index = RecvWithTimeout (s, 10.0f, http_buffer, sizeof (http_buffer), 0);
  232.    if (read_index < 1)
  233.    {
  234.       *failure_reason = LOCALIZE (L"Registration_NetworkFailure");
  235.       return (0); // empty or erroneous HTTP reply, return an error condition
  236.    }
  237.  
  238.    closesocket (s); // finished communicating, close TCP socket
  239.  
  240.    // terminate recv buffer and see where the useful data starts
  241.    http_buffer[read_index] = 0;
  242.    //MessageBoxA (NULL, http_buffer, "HTTP response", MB_OK);
  243.    if ((data_start = strstr (http_buffer, "Success=")) != NULL)
  244.    {
  245.       *failure_reason = L""; // no error, set an empty string as the failure reason
  246.       return ((unsigned __int32) atoll (&data_start[strlen ("Success=")])); // and return the candidate code we got
  247.    }
  248.    else if ((data_start = strstr (http_buffer, "Error=")) != NULL)
  249.    {
  250.       data_start += strlen ("Error=");
  251.       if (strchr (data_start, '\r') != NULL) *strchr (data_start, '\r') = 0;
  252.       if (strchr (data_start, '\n') != NULL) *strchr (data_start, '\n') = 0;
  253.       if      (_stricmp (data_start, "WrongEmail") == 0)         *failure_reason = LOCALIZE (L"Registration_WrongEmail");
  254.       else if (_stricmp (data_start, "UnknownEmail") == 0)       *failure_reason = LOCALIZE (L"Registration_UnknownEmail");
  255.       else if (_stricmp (data_start, "TooManyActivations") == 0) *failure_reason = LOCALIZE (L"Registration_TooManyActivations");;
  256.       return (0); // server returned an error, return an error condition
  257.    }
  258.  
  259.    *failure_reason = LOCALIZE (L"Registration_NetworkFailure"); // this should never happen
  260.    return (0); // server returned an error, return an error condition
  261. }
  262.