#include "pre.h" #include "tchar.h" #define LCID_JPN 1041 //JAPANESE // BUGBUG - This function is not very effecient since it requires a alloc/free for each validation // plus strtok will tokenize the fill string requring a full search of the string. BOOL IsValid(LPCTSTR pszText, HWND hWndParent, WORD wNameID) { ASSERT(pszText); TCHAR* pszTemp = NULL; BOOL bRetVal = FALSE; pszTemp = _tcsdup (pszText); if (pszTemp) { if (_tcslen(pszTemp)) { TCHAR seps[] = TEXT(" "); TCHAR* token = NULL; token = _tcstok( pszTemp, seps ); if (token) { bRetVal = TRUE; } } free(pszTemp); } // If not valid, give the user the error message if (!bRetVal) DoValidErrMsg(hWndParent, wNameID); return bRetVal; } // ============================================================================ // Credit card number validation // ============================================================================ // Takes a credit card number in the form of 1111-1111-1111-11 // and pads converts it to: // 11111111111111 // **IMPORTANT** :: This code is multibyte safe but ONLY because we care ONLY about // ANSI #'s BOOL PadCardNum ( LPCTSTR lpszRawCardNum, LPTSTR szPaddedCardNum, UINT uLenOfRaw ) { LPTSTR lpszTmp = CharPrev(lpszRawCardNum, lpszRawCardNum); UINT uIndex = 0; for (UINT i = 0; i < uLenOfRaw; i++) { if( *lpszTmp == '\0' ) break; if((*lpszTmp != '-') && (*lpszTmp != ' ')) { //make sure it's not some other than ansi char. if ((*lpszTmp < '0') || (*lpszTmp > '9')) return(FALSE); szPaddedCardNum[uIndex] = *lpszTmp; uIndex++; } // Get the prev char lpszTmp = CharNext(lpszRawCardNum + i); } szPaddedCardNum[uIndex] = '\0'; return(TRUE); } /* mod_chk() performs "Double-Add-Double MOD 10 Check Digit Routine" on card number */ BOOL mod_chk ( LPTSTR credit_card, UINT uCardNumLen ) { TCHAR *cp; int dbl = 0; int check_sum = 0; /* * This checksum algorithm has a name, * but I can't think of it. */ cp = credit_card + lstrlen(credit_card) - 1; while (cp >= credit_card) { int c; c = *cp-- - '0'; if (dbl) { c *= 2; if (c >= 10) c -= 9; } check_sum += c; dbl = !dbl; } return (BOOL)((check_sum % 10) == 0); } BOOL validate_cardnum(HWND hWndParent, LPCTSTR lpszRawCardNum) // performs: // a) card type prefix check // b) Double-Add-Double MOD 10 check digit routine via mod_chk() // on the card number. // The card_num parameter is assumed to have been pre-checked for // numeric characters and right-justified with '0' padding on the // left. { BOOL bRet = FALSE; UINT uRawLen = lstrlen(lpszRawCardNum); TCHAR* pszPaddedCardNum = (TCHAR*)malloc((uRawLen + 1)*sizeof(TCHAR)); if (!pszPaddedCardNum) return FALSE; ZeroMemory(pszPaddedCardNum ,(uRawLen + 1)*sizeof(TCHAR)); if (PadCardNum(lpszRawCardNum, pszPaddedCardNum, uRawLen)) { UINT i = 0; LPTSTR tmp_pt = pszPaddedCardNum; UINT uPadLen = lstrlen(pszPaddedCardNum); /* find the first non-zero number in card_num */ while (*tmp_pt == '0' && ++i < uPadLen) ++tmp_pt; /* all valid card types are at least 13 characters in length */ if (uPadLen < 13) bRet = FALSE; /* check for OK VISA prefix - 4 */ if ((uPadLen == 16 || uPadLen == 13) && *tmp_pt == '4') bRet = mod_chk(pszPaddedCardNum, uPadLen); /* check for OK MasterCard prefix - 51 to 55 */ if (uPadLen == 16) { if (*tmp_pt == '5' && *(tmp_pt + 1) >= '1' && *(tmp_pt + 1) <= '5') bRet = mod_chk(pszPaddedCardNum, uPadLen); } /* check for OK American Express prefix - 37 and 34 */ if (uPadLen == 15 && *tmp_pt == '3' && (*(tmp_pt + 1) == '7' || *(tmp_pt + 1) == '4')) bRet = mod_chk(pszPaddedCardNum, uPadLen); /* check for OK Discovery prefix - 6011 */ if (uPadLen == 16 && *tmp_pt == '6' && *(tmp_pt + 1) == '0' && *(tmp_pt + 2) == '1' && *(tmp_pt + 3) == '1') bRet = mod_chk(pszPaddedCardNum, uPadLen); } if (!bRet) { DoSpecificErrMsg(hWndParent, IDS_PAYMENT_CC_LUHNCHK); } free(pszPaddedCardNum); return bRet; } BOOL validate_cardexpdate(HWND hWndParent, int month, int year) { BOOL bRet = FALSE; SYSTEMTIME SystemTime; GetLocalTime(&SystemTime); if (year > SystemTime.wYear) { bRet = TRUE; } else if (year == SystemTime.wYear) { if (month >= SystemTime.wMonth) { bRet = TRUE; } } if (!bRet) { DoSpecificErrMsg(hWndParent, IDS_PAYMENT_CCEXPDATE); } return bRet; } // ============================================================================ // Error message handlers // ============================================================================ void DoValidErrMsg(HWND hWndParent, int iNameId) { TCHAR szCaption [MAX_RES_LEN+1] = TEXT("\0"); TCHAR szErrMsgFmt [MAX_RES_LEN+1] = TEXT("\0"); TCHAR szErrMsgName [MAX_RES_LEN+1] = TEXT("\0"); TCHAR szErrMsg [2*MAX_RES_LEN]; if (!LoadString(ghInstance, IDS_APPNAME, szCaption, ARRAYSIZE(szCaption))) return; if ((IDS_USERINFO_ADDRESS2 == iNameId) && (LCID_JPN == GetUserDefaultLCID())) iNameId = IDS_USERINFO_FURIGANA; if (!LoadString(ghInstance, iNameId, szErrMsgName, ARRAYSIZE(szErrMsgName))) return; if (!LoadString(ghInstance, IDS_ERR_INVALID_MSG, szErrMsgFmt, ARRAYSIZE(szErrMsgFmt))) return; wsprintf(szErrMsg, szErrMsgFmt, szErrMsgName); MessageBox(hWndParent, szErrMsg, szCaption, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL); } void DoSpecificErrMsg(HWND hWndParent, int iErrId) { TCHAR szCaption [MAX_RES_LEN+1] = TEXT("\0"); TCHAR szErrMsg [MAX_RES_LEN+1] = TEXT("\0"); if (!LoadString(ghInstance, IDS_APPNAME, szCaption, ARRAYSIZE(szCaption) )) return; if (!LoadString(ghInstance, iErrId, szErrMsg, ARRAYSIZE(szErrMsg) )) return; MessageBox(hWndParent, szErrMsg, szCaption, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL); }