Coding Sample
This is a program I wrote a while back and I present it here as an example of my coding style.A couple of things I strive for in code is neatness and lots of comments.
And I try not to be obtuse. I know it's kind of fun to be terse and efficient, even clever,
but in the end this stuff has to be maintained and keeping it simple/stupid
is probably a better strategy. I always spent time designing a good log file for
troubleshooting down the road.
What follows is a COM object written in C, to be used by ASP/IIS websites to create a unique identifier
for a person and add a record to a LDAP database, making sure to avoid duplicates.
The new id is accessed by the PersonNumber property of the object and any
error messages are accessed in the Messages property, which is a 2-dimensional
array. This was my first COM object to be consumed by VB code in an ASP page and it took
a week to get the 2-dimensional array passed back to the web page. I thought I had the
problem licked when I first tried passing just an int, but each move to the next level of
complexity, a string, a one dimensional array and finally the 2-d array, was a new challenge.
I had no idea what I was doing, but that's the fun part.
The consuming code in the ASP page would look like this:
Set objPN = Server.CreateObject("AssignPNObject.AssignPNObject.1")
retCode = objPN.AssignNumber(ssn, firstName, middleInitial , lastName,
birthDate, gender, forceNumberIndicator)
num = objPN.PersonNumber
if retCode = 0 then
response.write("Person Number : " & num)
elseif retCode = 4 then
response.write("Person Number : " & num)
elseif retCode = 6 then
response.write("An Existing Person Number was returned : " & num)
elseif retCode = 8 then
response.write("Validations error. No person Number assigned.")
elseif retCode = 12 then
response.write("Failed Assign attempt. ")
end if
if retCode > 0 then
msgQuan = objPN.msgQuantity
if msgQuan > 0 then
response.write("Num messages : " & msgQuan)
msgs = objPN.Messages
response.write("ubound dim 1 : " & UBound(msgs,1))
response.write("ubound dim 2 : " & UBound(msgs, 2)
for i = lbound(msgs,1) to ubound(msgs,1)
response.write("Num : " & msgs(i,0) )
response.write("Sev : " & msgs(i,1))
response.write("Text : " & msgs(i,2))
next
end if
end if
set objPN = Nothing
And here's the C code for the COM object.
// AssignPNObject.cpp : Implementation of CAssignPNObject #include "stdafx.h" #include "AssignPersonNumber.h" #include "AssignPNObject.h" ///////////////////////////////////////////////////////////////////////////// // CAssignPNObject STDMETHODIMP CAssignPNObject::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_IAssignPNObject, }; for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++) { if (InlineIsEqualGUID(*arr[i],riid)) return S_OK; } return S_FALSE; } STDMETHODIMP CAssignPNObject::AssignNumber(BSTR bstrInSSN, BSTR bstrInFN, BSTR bstrInMI, BSTR bstrInLN, BSTR bstrInBD, BSTR bstrInG, BSTR bstrInFNI, short *pVal) { m_msgQuantity = 0; // initial number of msgs to zero m_PersonNumber = 0; // The input parms come in as BSTR's, but the LDAP API wants to see strings, // so the BSTR's must be converted to strings. This is a 2 step process - // 1. first convert BSTR to multiBytes and then to strings (with a strcpy). // For each input parameter: // 1. declare the 2 element array the first elem will hold the string attr value // 2. declare a string and a multibye to hold the data during the conversion // 3. convert from bstr to multibyte using the windows API WideCharToMultiByte // 4. convert the multibyte to string using strcpy // SSN char strSSN[10] = ""; TCHAR mbSSN[10] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInSSN, -1, mbSSN,10, NULL, NULL); strcpy(strSSN, mbSSN); // first name - given name char strFN[31] = ""; TCHAR mbFN[31] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInFN, -1, mbFN,31, NULL, NULL); strcpy(strFN, mbFN); // middle initial //char strMI[2]; char strMI[2] = ""; TCHAR mbMI[2] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInMI, -1, mbMI,2, NULL, NULL); strcpy(strMI, mbMI); // sn - sur name - last name char strLN[31] = ""; TCHAR mbLN[31] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInLN, -1, mbLN, 31 , NULL, NULL); strcpy(strLN, mbLN); // birth date char strBD[11] = ""; TCHAR mbBD[11] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInBD, -1, mbBD,11, NULL, NULL); strcpy(strBD, mbBD); // gender char strG[2] = ""; TCHAR mbG[2] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInG, -1, mbG, 2 , NULL, NULL); strcpy(strG, mbG); // force number indicator char strFNI[2] = ""; TCHAR mbFNI[2] = ""; WideCharToMultiByte(CP_ACP, 0, bstrInFNI, -1, mbFNI,2, NULL, NULL); strcpy(strFNI, mbFNI); // Now that we have strings for all the input params, // let's do the edits on the input data int validData = 0; validData = validateInput( strSSN, strFN, strMI, strLN, strBD, strG, strFNI); if (validData > 3) { *pVal = 8; return S_OK; } //*********************************************************************** // OK time to assign the person number. // Note that more checking goes on in assignNumber - looking for an entry // with attributes that match or come close to matching the current input // params. If a match is found, a new person number entry is not done, // so at this point, all may not be hunky dory. //3000-AssignNumber Procedure int retCode = 0; retCode = assignTheNumber( strSSN, strFN, strMI, strLN, strBD, strG, strFNI); *pVal = retCode; return S_OK; } //***************************************************************************** //**************** END OF MAIN ************************ //***************************************************************************** //***************************************************************************** //***************************************************************************** //***** All the get property functions exposed to the client are here ****** //***************************************************************************** STDMETHODIMP CAssignPNObject::get_MsgQuantity(short * pVal) { // TODO: Add your implementation code here *pVal = m_msgQuantity; return S_OK; } STDMETHODIMP CAssignPNObject::get_PersonNumber(long * pVal) { // TODO: Add your implementation code here *pVal = m_PersonNumber; return S_OK; } STDMETHODIMP CAssignPNObject::get_Messages(VARIANT * pVal) { int lgth = 0; char strMsgNum[200] = ""; char strMsgSev[2] = ""; char strMsgText[144] = ""; char strBB[200] = ""; int z = 0; int row = 0; int i = 0; long ndx[2]; CComBSTR bstrVal(200, strBB); CComVariant varVal; SAFEARRAYBOUND bounds[] = {{m_msgQuantity,0}, {3, 0}}; VariantInit(pVal); pVal->vt = VT_VARIANT | VT_ARRAY; pVal->parray = SafeArrayCreate(VT_VARIANT, 2, bounds); TCHAR mbMsg[200]; std::vector<CComBSTR>::iterator it; char strMessage[200]; for (i = 0; i < 200; i++ ) strMessage[i] = NULL; for (it = m_vecMsgs.begin(); it != m_vecMsgs.end(); it++, row++) { WideCharToMultiByte(CP_ACP, 0, ((*it).m_str), -1, mbMsg,200, NULL, NULL); strcpy(strMessage, mbMsg); strncpy(strMsgNum, strMessage, 6); strMsgNum[6] = '\0'; bstrVal.Empty(); bstrVal.Append(strMsgNum); varVal = bstrVal; ndx[0] = row; ndx[1] = 0; SafeArrayPutElement(pVal->parray, ndx, &varVal); // Now do the severity flag strMsgSev[0] = strMessage[7]; strMsgSev[1] = '\0'; bstrVal.Empty(); bstrVal.Append(strMsgSev); varVal = bstrVal; ndx[0] = row; ndx[1] = 1; SafeArrayPutElement(pVal->parray, ndx, &varVal); // Now do the text lgth = strlen(strMessage); //lgth = lgth - 8; for (i = 9; i < lgth; i++) { strMsgText[z] = strMessage[i]; z++; } strMsgText[z] = '\0'; bstrVal.Empty(); bstrVal.Append(strMsgText); varVal = bstrVal; ndx[0] = row; ndx[1] = 2; SafeArrayPutElement(pVal->parray, ndx, &varVal); for (i = 0; i < lgth; i++ ) strMsgText[i] = NULL; z = 0; } return S_OK; } //************************************************************************ //************************************************************************ //****************** Input fields validation routines ****************** //************************************************************************ //************************************************************************ //2000-validateInput int CAssignPNObject::validateInput(char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { int goodDataFlag = 0; int retVal = 0; if (strlen(strSSN) > 0) { goodDataFlag = validateSSN( strSSN ); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } } goodDataFlag = validateGenderCode(strG); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } goodDataFlag = validateName( strFN, strMI, strLN ); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } goodDataFlag = validateBirthDate( strBD ); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } goodDataFlag = validateGenderCode( strG ); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } goodDataFlag = validateFNI( strFNI, strSSN); if ( goodDataFlag != 0) { retVal = goodDataFlag; goodDataFlag = 0; } return retVal; } //2100-validateSSN int CAssignPNObject::validateSSN( char* strSSN ) { int retVal = 0; int badFlag = 0; if (strlen(strSSN) < 9 || strlen(strSSN) > 9) badFlag = 1; if (badFlag == 0) { for (int i = 0; i < 9; i++) { if (isdigit( strSSN[i] ) == 0) { badFlag = 1; } } } // Now make sure ssn is in range if (badFlag == 0) { int ssn = atoi( strSSN ); if ( (ssn < 1000000 && ssn != 0) || (ssn > 766999999) ) { badFlag = 1; } } if (badFlag == 1) { char err[140] = "PN0010!R!invalid SSN "; strcat( err, strSSN ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } return retVal; } //2200-validateName int CAssignPNObject::validateName( char* strFN, char* strMI, char* strLN ) { int retVal = 0; int badFlag = 0; int i = 0; if (strcmp(strFN, "") == 0 ) { badFlag = 1; char err[140] = "PN0002!R!first name required"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } if (strcmp(strLN, "") == 0 ) { char err[140] = "PN0005!R!last name required"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } if (strlen(strFN) > 30) { char err[140] = "PN0004!R!first name length > 30 characters"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } if (strlen(strLN) > 30) { badFlag = 1; char err[140] = "PN0004!R!last name length > 30 characters"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } if (strcmp( strMI, " ") == 0) strcpy (strMI, " "); if (strlen(strMI) > 1) { char err[140] = "PN0004!R!middle initial length > 1 character"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } for ( i = 0; i < strlen(strFN); i++ ) { if ( !(isalpha( strFN[i] )) ) { if ( strFN[i] != ' ' && strFN[i] != '.' && strFN[i] != 39 && strFN[i] != '-') { char err[140] = "PN0004!R!first name : "; strcat( err, strFN); strcat(err, " not alphabetic"); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } } } for ( i = 0; i < strlen(strLN); i++ ) { if ( !(isalpha( strLN[i] )) ) { if ( strLN[i] != ' ' && strLN[i] != '.' && strLN[i] != 39 && strLN[i] != '-') { char err[140] = "PN0004!R!last name : "; strcat( err, strLN); strcat(err, " not alphabetic"); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } } } for ( i = 0; i < strlen(strMI); i++ ) { if ( !(isalpha( strMI[i] )) ) { if ( strMI[i] != ' ') { char err[140] = "PN0004!R!middle initial : "; strcat( err, strMI); strcat(err, " not alphabetic"); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } } } return retVal; } //2300-validateBirthDate int CAssignPNObject::validateBirthDate( char* strBD ) { int retVal = 0; int badFlag = 0; // get the rundate year int todaysYear; time_t timer; struct tm *sys_time; time(&timer); sys_time = localtime(&timer); todaysYear = sys_time->tm_year - 100 + 2000; if (strcmp(strBD, "") == 0 ) { badFlag = 1; char err[140] = "PN0002!R!birth date required"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } else { if (isdigit( strBD[0] ) == 0) badFlag = 1; else if (isdigit( strBD[1] ) == 0) badFlag = 1; else if (strBD[2] != '/') badFlag = 1; else if (isdigit( strBD[3] ) == 0) badFlag = 1; else if (isdigit( strBD[4] ) == 0) badFlag = 1; else if (strBD[2] != '/') badFlag = 1; else if (isdigit( strBD[6] ) == 0) badFlag = 1; else if (isdigit( strBD[7] ) == 0) badFlag = 1; else if (isdigit( strBD[8] ) == 0) badFlag = 1; else if (isdigit( strBD[9] ) == 0) badFlag = 1; else { char dd[3] = ""; char mm[3] = ""; char yy[5] = ""; mm[0] = strBD[0]; mm[1] = strBD[1]; mm[2] = '\0'; dd[0] = strBD[3]; dd[1] = strBD[4]; dd[2] = '\0'; yy[0] = strBD[6]; yy[1] = strBD[7]; yy[2] = strBD[8]; yy[3] = strBD[9]; yy[4] = '\0'; int iyy = atoi( yy ); int idd = atoi( dd ); int imm = atoi( mm ); if (iyy < 1900 || iyy > todaysYear) badFlag = 1; else if ( imm < 1 || imm > 12 ) badFlag = 1; else if ( imm == 1 || imm == 3 || imm == 5 || imm == 7 || imm == 8 || imm == 10 || imm == 12) { if (idd < 1 || idd > 31 ) badFlag = 1; } else if ( imm == 4 || imm == 6 || imm == 9 || imm == 11) { if (idd < 1 || idd > 30 ) badFlag = 1; } else if (imm == 2) { if (( iyy % 4 ) == 0) if (idd < 1 || idd > 29 ) badFlag = 1; else if (idd < 1 || idd > 28 ) badFlag = 1; } } if (badFlag == 1) { char err[140] = "PN0002!R!invalid birth date : "; strcat( err, strBD); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } } return retVal; } //2400-validateGenderCode int CAssignPNObject::validateGenderCode( char* strG ) { int retVal = 0; if (strcmp(strG, "") == 0 ) { char err[140] = "PN0013!R!gender required"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } else if (strG[0] != 'M' && strG[0] != 'F') { char err[140] = "PN0014!R!invalid gender code : "; strcat( err, strG); strcat( err, " not F or M"); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } return retVal; } //2500-validateFNI int CAssignPNObject::validateFNI( char* strFNI, char* strSSN ) { int retVal = 0; if (strFNI[0] != 'N' && strFNI[0] != 'Y') { char err[140] = "PN0015!R!force option "; strcat( err, strFNI); strcat( err, " not Y or N"); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } else if ( strFNI[0] == 'Y' && (strcmp(strSSN, "") != 0)) { char err[140] = "PN0017!R!force option of yes not allowed is SSN specified"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } return retVal; } //************************************************************************ //************************************************************************ //****************** Assign The Number routines ****************** //************************************************************************ //************************************************************************ //3000-assignTheNumber int CAssignPNObject::assignTheNumber(char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { int isPersonThere = 0; long personNumber = 0; char strPersonNumber[9] = ""; char ForcedSeqNum[6] = "0"; // All the LDAP related variables and constants LDAP *ld; // handle to the directory int rc; // return code for calling some LDAP API functions // user and password for binding to the directory char *dn = "cn=password, ou=zzz, ou=qqq, o=acme inc, c=us"; char *pw = "mypw"; // Get a handle to an LDAP connection. if ( (ld = ldap_init( "serverBob", port100 )) == NULL ) { char *err = "PN0001!R!directory not available 3000-init"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); return 12; } // Bind to the LDAP server. rc = ldap_simple_bind_s( ld, dn, pw ); if ( rc != LDAP_SUCCESS ) { char *err = "PN0001!R!directory not available3000 bind"; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); return 12; } // We change a NULL SSN to zero. LDAP needs a dummy value if (strcmp(strSSN, "") == 0) strcpy(strSSN, "0"); // if the return code, isPersonThere = 4, this is just a warning and we should proceed to // create a new PN and add the entry to the tree. isPersonThere = CheckForPersonExistence(ld, strSSN, strFN, strMI, strLN, strBD, strG, strFNI, ForcedSeqNum); // if return = 4 - warning msgs, but proceed with add // 6 - warning msgs, return existing PN - No new entry // 7 - warning msgs, no number returned - No new entry if (isPersonThere < 5) { // When adding an entry, a struct of type LDAPMod must exist for each attribute of the entry. // Each struct contains a 2 element array containing the attr value and a NULL. // (This is 2 elements because the personNumber attribs are all single value.) // if no SSN and FNI = Y, we don't write and ssn attrib but we do write an Forced Seq# char *bbSsnCode_vals[2]; char *givenName_vals[2]; char *initials_vals[2]; char *sn_vals[2]; char *bbBirthDate_vals[2]; char *bbGender_vals[2]; char *bbForceNumberIndicator_vals[2]; char *uid_vals[2]; char *bbForceSequenceNumber_vals[2]; // Now declare the LDAPMod structures, one for each attribute LDAPMod uidMod, snMod, givenNameMod, initialsMod, bbSsnCodeMod, bbGenderMod, bbBirthDateMod, bbForceNumberIndicatorMod, bbForceSequenceNumberMod, ocMod; // the object class attribute // Now declare the array of pointers to the LDAPMod structures // This is what is passed as a parm to the LDAP ADD API LDAPMod *mods[11]; for (int i=0; i<11; i++) mods[i] = NULL; // now generate a new person number personNumber = generatePersonNumber(strLN); m_PersonNumber = personNumber; // Place it into the member variable // Convert the person number to a string convertPNToString(personNumber, strPersonNumber); // The new DN is passed to the LDAP add call. For the person number object it looks like : // "uid=12345678, ou=Person Number, o=Acme Inc, c=us" // assuming the person number is 12345678. // Since the person number, ie. uid, has not yet been calculated, we split the string // in two here for later inclusion of the uid with the strcat function char newDN[57] = ""; char newDNPartOne[5] = "uid="; char newDNPartTwo[44] = ", ou=Person Number, o=acme Inc, c=us"; // The LDAP API add call needs an entry DN, which we can create now that we have a // uid, aka person number, as the uid is part of the DN (distinguished name) strcpy(newDN, newDNPartOne); strcat(newDN, strPersonNumber); strcat(newDN, newDNPartTwo); // Put the value of each attribute into it's array. // SSN bbSsnCode_vals[0] = strSSN; bbSsnCode_vals[1] = NULL; // first name - given name givenName_vals[0] = strFN; givenName_vals[1] = NULL; // middle initial initials_vals[0] = strMI; initials_vals[1] = NULL; // sn - sur name - last name sn_vals[0] = strLN; sn_vals[1] = NULL; // birth date bbBirthDate_vals[0] = strBD; bbBirthDate_vals[1] = NULL; // gender bbGender_vals[0] = strG; bbGender_vals[1] = NULL; // force number indicator bbForceNumberIndicator_vals[0] = strFNI; bbForceNumberIndicator_vals[1] = NULL; // forced sequence number bbForceSequenceNumber_vals[0] = ForcedSeqNum; bbForceSequenceNumber_vals[1] = NULL; //uid - person number uid_vals[0] = strPersonNumber; uid_vals[1] = NULL; // declare the object class level array using hardcoded initialization data char *oc_vals[] = { "top" , "bbPersonNumber", NULL }; // Now fill in the values in each LDAPMod structure. The mod_op is TO ADD AN ENTRY. // The mod_type is the type of attribute that particular LDAPMod struct is for. // mod_valuse is the 2 dimensional array for each attribute ocMod.mod_op = 0; ocMod.mod_type = "objectclass"; ocMod.mod_values = oc_vals; uidMod.mod_op = 0; uidMod.mod_type = "uid"; uidMod.mod_values = uid_vals; snMod.mod_op = 0; snMod.mod_type = "sn"; snMod.mod_values = sn_vals; givenNameMod.mod_op = 0; givenNameMod.mod_type = "givenname"; givenNameMod.mod_values = givenName_vals; bbSsnCodeMod.mod_op = 0; bbSsnCodeMod.mod_type = "bbSsnCode"; bbSsnCodeMod.mod_values = bbSsnCode_vals; initialsMod.mod_op = 0; initialsMod.mod_type = "initials"; initialsMod.mod_values = initials_vals; bbGenderMod.mod_op = 0; bbGenderMod.mod_type = "bbGender"; bbGenderMod.mod_values = bbGender_vals; bbBirthDateMod.mod_op = 0; bbBirthDateMod.mod_type = "bbBirthDate"; bbBirthDateMod.mod_values = bbBirthDate_vals; bbForceNumberIndicatorMod.mod_op = 0; bbForceNumberIndicatorMod.mod_type = "bbForceNumberIndicator"; bbForceNumberIndicatorMod.mod_values = bbForceNumberIndicator_vals; bbForceSequenceNumberMod.mod_op = 0; bbForceSequenceNumberMod.mod_type = "bbForceSequenceNumber"; bbForceSequenceNumberMod.mod_values = bbForceSequenceNumber_vals; mods[0] = &uidMod, mods[1] = &snMod, mods[2] = &givenNameMod, mods[3] = &bbSsnCodeMod, //mods[4] = &initialsMod, mods[4] = &bbGenderMod, mods[5] = &bbBirthDateMod, mods[6] = &bbForceNumberIndicatorMod, mods[7] = &bbForceSequenceNumberMod, mods[8] = &ocMod; //mods[10] = NULL; // mi is optional, so if it's blank or null dont send LDAP a mod struct for the mi attrib // if you send something such as a blank or null, LDAP complains if ( strcmp( strMI, "") != 0 && strcmp( strMI, " ") != 0) { initials_vals[0] = strMI; initials_vals[1] = NULL; initialsMod.mod_op = 0; initialsMod.mod_type = "initials"; initialsMod.mod_values = initials_vals; mods[9] = &initialsMod, mods[10] = NULL; } // Perform the add operation. int returnAdd = 68; // init to 68 which is the LDAP ret val for a dup entry while (returnAdd == 68) // while ret val = dup, try again to add { returnAdd = addEntry(ld, newDN, mods); if (returnAdd == 68) // duplicate { // the last generated pn was a duplicate - rare occurrence. // make a new number - new distinguished name string // put the number into the mod array personNumber = generatePersonNumber(strLN); //personNumber = personNumber + 9; //old way just bump by 9 and try again convertPNToString(personNumber, strPersonNumber); strcpy(newDN, newDNPartOne); strcat(newDN, strPersonNumber); strcat(newDN, newDNPartTwo); m_PersonNumber = personNumber; // Place it into the member variable // Place it in its 2 dimensional array uid_vals[0] = strPersonNumber; uid_vals[1] = NULL; } // end goodAdd if else if (returnAdd !=0) { // had a problem. Create a message and set goodAdd = 0 to get out of loop. // To include the return code (goodAdd) in the message, convert it to a string. // Ret codes will be 1 or 2 digits. If the code is a single digit, say 7, ecvt will // put 70 in the returned string. So convert the string back to an int to make // sure it still = the original number. If it's 10 times the orig, we know it was // a single digit, so lop off that extra 0 in the string. char* strRetCode; int decimal_spot, sign; // find out how many digits the ret code is for the ecvt function call int y; int x = returnAdd / 10; // string back to an int if (x < 1) { y = 1; } else if (x < 10) { y = 2; } else if (x < 100) { y = 3; } strRetCode = ecvt (returnAdd, y, &decimal_spot, &sign); // int to string 2 chars long char err[140] = "PN0001!R!Directory not available. Return code from LDAP ADD operation : "; strcat( err, strRetCode ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); returnAdd = 12; // lets not loop forever } } // end goodAdd while } // end personThere if ldap_unbind_s( ld ); return isPersonThere; } // end assign function //3100-CheckForPersonExistence // Decide whether to continue with a new assign or return an existing PN. int CAssignPNObject::CheckForPersonExistence( LDAP * ld, char* strSSN, char* strFN, char* strMI,char* strLN, char* strBD, char* strG, char* strFNI, char* ForcedSeqNum) { // 2 possibilities here. //If an SSN was input as a parm, see if there's a match in the person number //tree already. If not, go back and add this new person. If so: // - int isPersonThere = 0; if ( strcmp(strSSN, "0" ) != 0) { isPersonThere = CheckForPersonExistenceWithSSN( ld, strSSN, strFN, strMI, strLN, strBD, strG, strFNI ); } else { //isPersonThere = 666; isPersonThere = CheckForPersonExistenceWithoutSSN(ld, strSSN, strFN, strMI, strLN, strBD, strG, strFNI, ForcedSeqNum); } return isPersonThere; } //3110-CheckForPersonExistenceWithSSN // Fisrt see if there's an existing entry with the same ssn. // If there is not, check to see if there's an entry with any SSN and all // of the remaining attributes. If this 'close match' is found,(all but SSN), // return a a warning message, but this program will still assign a new Person // number and add an entry to the PN tree. // If there is one SSN match found, (later in this program, a new PN is not generated // nor will an new entry be made). // Then check the matched (existing) entry's attribs to see if // how closely they match. For each attrib, if it doesnt match the input attribs, // generate a warning message to inform the user that an anomoly condition // may exist. // If more than one SSN match is found, loop through match and just create a warning // message for each one. int CAssignPNObject::CheckForPersonExistenceWithSSN( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int retVal = 0; char storedPN[9] = ""; int rc, num_entries = 0, num_refs = 0; int isPersonThere = 0; struct attributes // struct to hold the attribute vals for { // an entry that's almost a duplicate char storedSSN[10]; char storedFN[31]; char storedMI[31]; char storedLN[31]; char storedBD[31]; char storedG[31]; char storedFNI[31]; } storedPersonAttributes; struct attributes* ptr_storedPerson; ptr_storedPerson = &storedPersonAttributes; char strFilter[200] = ""; strcat( strFilter, "(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char *err = "PN0001!R!directory not available -chk for exist w ssn "; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; // bad return code - trouble with the ldap call } else { num_entries = ldap_count_entries( ld, result ); // any hits? if (num_entries == 0) { // no other entry with this ssn. Now check for one with all attrs but ssn. // Note if there is one, a warning is generated, but generation of // a new PN continues. int closeOne = 0; closeOne = CheckForPersonExistenceWithSSNWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI ); retVal = closeOne; } else if (num_entries == 1) { retVal = 6; int mismatchFlag = 0; e = ldap_first_entry( ld, result ); // Iterate through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // For each attribute, print the attribute name and values. // All single val attributes, so use vals[0] if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy(storedPN, vals[0]); m_PersonNumber = atol(storedPN); } else if (strcmp(a, "givenName") == 0) { if (strcmp(strFN, vals[0] ) != 0) { char err[140] = "PN0019!W!SSN match, first name mismatch. Input : "; strcat( err, strFN ); strcat( err, " stored : " ); strcat( err, vals[0] ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); mismatchFlag = 1; } } else if (strcmp(a, "initials") == 0) { if (strcmp(strMI, vals[0] ) != 0) { char err[140] = "PN0021!W!SSN match, middle initial mismatch. Input : "; strcat( err, strMI ); strcat( err, " stored : " ); strcat( err, vals[0] ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); mismatchFlag = 1; } } else if (strcmp(a, "sn") == 0) { if (strcmp(strLN, vals[0] ) != 0) { char err[140] = "PN0020!W!SSN match, last name mismatch. Input : "; strcat( err, strLN ); strcat( err, " stored : " ); strcat( err, vals[0] ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); mismatchFlag = 1; } } else if (strcmp(a, "bbGender") == 0) { if (strcmp(strG, vals[0] ) != 0) { char err[140] = "PN0023!W!SSN match, gender mismatch. Input : "; strcat( err, strG ); strcat( err, " stored : " ); strcat( err, vals[0] ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); mismatchFlag = 1; } } else if (strcmp(a, "bbBirthDate") == 0) { if (strcmp(strBD, vals[0] ) != 0) { char err[140] = "PN0022!W!SSN match, birth date mismatch. Input : "; strcat( err, strBD ); strcat( err, " stored : " ); strcat( err, vals[0] ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); mismatchFlag = 1; } } // end big if else - one if for each possible attribute } // end the loop through the attributes ldap_value_free( vals ); } // end of looping through the entries ldap_memfree( a ); if (mismatchFlag == 0) { mismatchFlag = 0; char err[140] = "PN0018!W!All attributes match an exisiting entry. Person Number : "; strcat( err, storedPN ); strcat( err, " , existing PN returned" ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); } } else if (num_entries > 1) { retVal = 7; for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // Iterate through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Produce a message containing the matched entry's person number if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { char err[140] = "PN0030!R!For SSN :"; strcat( err, strSSN ); strcat( err, " more than one person already existing. Existing PN : " ); strcat( err, vals[0] ); // single value attribute : vals[0] m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } } // end the loop through entry - one loop per attribute ldap_value_free( vals ); } // end of looping through the attributes ldap_memfree( a ); } // end of for looping through the entries - go to for loop top to get next entry } // end of if els if ( ber != NULL ) ber_free( ber, 0 ); ldap_msgfree( result ); } return retVal; // bad return code - trouble with the ldap call } //3120-CheckForPersonExistenceWithoutSSN int CAssignPNObject::CheckForPersonExistenceWithoutSSN( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI, char* ForcedSeqNum) { int isPersonThere = 0; isPersonThere = CheckForPersonExistenceWithAllNonSSNAttributes(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI, ForcedSeqNum); if (isPersonThere == 0) { isPersonThere = CheckForPersonExistenceWithSSNWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); isPersonThere = CheckForPersonExistenceWithFirstNameWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); isPersonThere = CheckForPersonExistenceWithMiddleIWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); isPersonThere = CheckForPersonExistenceWithLastNameWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); isPersonThere = CheckForPersonExistenceWithBirthDateWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); isPersonThere = CheckForPersonExistenceWithGenderWildCard(ld, strSSN, strFN, strMI,strLN,strBD,strG, strFNI); } return isPersonThere; } //3121-CheckForPersonExistenceWithAllNonSSNAttributes int CAssignPNObject::CheckForPersonExistenceWithAllNonSSNAttributes( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI, char* ForcedSeqNum) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedForcedSeqNum[6] = ""; char storedPN[9] = ""; int iSeqNum = 0; int prevSeqNum = 0; long lSeqNum = 0; char storedSSN[10] = ""; LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; int retVal = 0; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode=0)"); strcat( strFilter, "(givenName="); strcat( strFilter, strFN); strcat( strFilter, ")(initials="); strcat( strFilter, strMI); strcat( strFilter, ")(sn="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); //char err[150] = "BB in CheckForPersonExistenceWithAllNonSSNAttributes TOP "; //strcat( err, strFilter); //m_msgQuantity ++; //m_vecMsgs.push_back(CComBSTR(err)); if (rc != 0) { char *err = "PN0001!R!directory not available -chk for exist w ssn "; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; // bad return code - trouble with the ldap call } else { num_entries = ldap_count_entries( ld, result ); // any hits? if (num_entries == 0) { if (strcmp(strFNI, "Y") == 0) { char err[140] = "PN0016!R!Force option of yes specified, but no matching person found. No PN returned."; m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 8; } else retVal = 0; } else if(num_entries == 1) { // first get the vals of the uid and StoredForce Number attributes e = ldap_first_entry( ld, result ); // Iterate through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // For each attribute, print the attribute name and values. // All single val attributes, so use vals[0] if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy(storedPN, vals[0]); } else if (strcmp(a, "bbForceSequenceNumber") == 0) { strcpy(storedForcedSeqNum, vals[0]); iSeqNum = atoi(storedForcedSeqNum); } } // end the loop through the attributes - one loop per attribute ldap_value_free( vals ); } // end of looping through the entries ldap_memfree( a ); if (strcmp(strFNI, "N") == 0) { retVal = 7; m_PersonNumber = atol(storedPN); // return the stored number don't force a new one char err[150] = "PN0032!W!For"; strcat(err, strSSN);strcat(err, " "); strcat(err, strFN);strcat(err, " "); strcat(err, strMI);strcat(err, " "); strcat(err, strLN);strcat(err, " "); strcat(err, strBD);strcat(err, " "); strcat(err, strG); strcat(err, "one PN "); strcat(err, storedPN); strcat(err, " found. Returning stored PN."); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); } else { iSeqNum = (atoi(storedForcedSeqNum)); iSeqNum++; int y; int x = iSeqNum / 10; // string back to an int if (x < 1) // was it a 1 or 2 digit return code { y = 1; // it was 1 digit, so lop off the 10's place } else if (x < 10) // was it a 1 or 2 digit return code { y = 2; } else if (x < 100) // was it a 1 or 2 digit return code { y = 3; } else if (x < 1000) // was it a 1 or 2 digit return code { y = 4; } int decimal_spot, sign; // These end up being throw aways char *pn; pn = ecvt (iSeqNum, y, &decimal_spot, &sign); strcpy(ForcedSeqNum, pn); retVal = 0; // go ahead and create a new person number //char err[150] = "BB found 1 match FNI = Y , stored seq num = "; //strcat(err, storedForcedSeqNum ); //strcat( err, " sending back val of "); //strcat(err, ForcedSeqNum ); //m_msgQuantity ++; //m_vecMsgs.push_back(CComBSTR(err)); } } else if (num_entries > 1) { //char err[150] = "BB in CheckForPersonExistenceWithAllNonSSNAttributes NE > 1 "; //m_msgQuantity ++; //m_vecMsgs.push_back(CComBSTR(err)); for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // Iterate through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Produce a message containing the matched entry's person number if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy(storedPN, vals[0]); //m_PersonNumber = atol(storedPN); } else if (strcmp(a, "bbForceSequenceNumber") == 0) { strcpy(storedForcedSeqNum, vals[0]); iSeqNum = atoi(storedForcedSeqNum); } } } // end the loop through the attributes ldap_value_free( vals ); if (strcmp(strFNI, "N") == 0) { char err[150] = "PN0031!R!For "; strcat(err, strFN);strcat(err, " "); strcat(err, strMI);strcat(err, " "); strcat(err, strLN);strcat(err, " "); strcat(err, strBD);strcat(err, " "); strcat(err, strG); strcat(err, ", more than one PN "); strcat(err, storedPN); strcat(err, " found. No PN will be returned. "); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 7; } else { // We'll force a new number so get the largest FseqNum value // We'll increment it one more for this new entry if (iSeqNum > prevSeqNum) prevSeqNum = iSeqNum; //char err[150] = "BB Loop found > 1 match FNI = Y , stored seq num = "; //strcat(err, storedForcedSeqNum ); //strcat( err, "sending back val of "); //strcat(err, ForcedSeqNum ); //m_msgQuantity ++; //m_vecMsgs.push_back(CComBSTR(err)); } } // end of looping through the entries ldap_memfree( a ); if (strcmp(strFNI, "Y") == 0) { // convert the ForcedSeqNum to a string for the new add iSeqNum++; int y; int x = iSeqNum / 10; // string back to an int if (x < 1) // was it a 1 or 2 digit return code { y = 1; // it was 1 digit, so lop off the 10's place } else if (x < 10) // was it a 1 or 2 digit return code { y = 2; } else if (x < 100) // was it a 1 or 2 digit return code { y = 3; } else if (x < 1000) // was it a 1 or 2 digit return code { y = 4; } int decimal_spot, sign; // These end up being throw aways char *pn; pn = ecvt (iSeqNum, y, &decimal_spot, &sign); strcpy(ForcedSeqNum, pn); retVal = 0; // go ahead and create a new person number //char err[150] = "BB Final found > 1 match FNI = Y , stored seq num = "; //strcat(err, storedForcedSeqNum ); //strcat( err, "sending back val of "); //strcat(err, ForcedSeqNum ); //m_msgQuantity ++; //m_vecMsgs.push_back(CComBSTR(err)); } } // end of if num_entry elses if ( ber != NULL ) ber_free( ber, 0 ); ldap_msgfree( result ); } return retVal; } //3122-CheckForPersonExistenceWithSSNWildCard // Looks for an entry with all the same attributes (except ssn), equal to those of the person // for which a new PN is being asked for - ie the input params to AssignNumber. int CAssignPNObject::CheckForPersonExistenceWithSSNWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedSSN[11] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); // ssn=* is the same as not including ssn in the filter strcat( strFilter, "*"); strcat( strFilter, ")(givenName="); strcat( strFilter, strFN); if ( strcmp( strMI, "") != 0 && strcmp( strMI, "") != 0 ) { strcat( strFilter, ")(initials="); strcat( strFilter, strMI); } strcat( strFilter, ")(surname="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable. SSN=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "bbSsnCode") == 0) { strcpy( storedSSN, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes ldap_value_free( vals ); ldap_memfree( a ); char err[150] = "PN0029!W!possible PN duplicate. SSN is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, " Stored SSN : "); strcat( err, storedSSN ); strcat( err, " Input SSN : "); strcat( err, strSSN ); m_vecMsgs.push_back(CComBSTR(err)); m_msgQuantity ++; } // end of for looping through the entry - go to for loop top to get next entry } } return retVal; } //3123-CheckForPersonExistenceWithFirstNameWildCard int CAssignPNObject::CheckForPersonExistenceWithFirstNameWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedGivenName[31] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")(givenName="); strcat( strFilter, "*"); if ( strcmp( strMI, "") != 0 && strcmp( strMI, "") != 0 ) { strcat( strFilter, ")(initials="); strcat( strFilter, strMI); } strcat( strFilter, ")(surname="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable FN=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "givenName") == 0) { strcpy( storedGivenName, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes ldap_value_free( vals ); ldap_memfree( a ); char err[150] = "PN0025!W!possible PN duplicate. First Name is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, ", Stored First Name : "); strcat( err, storedGivenName ); strcat( err, ", Input First Name : "); strcat( err, strFN ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); } // end of for looping through the entries - go to for loop top to get next entry } } return retVal; } //3124-CheckForPersonExistenceWithMiddleIWildCard int CAssignPNObject::CheckForPersonExistenceWithMiddleIWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedMI[2] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")(givenName="); strcat( strFilter, strFN); strcat( strFilter, ")(initials="); strcat( strFilter, "*"); strcat( strFilter, ")(surname="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable. MI=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "initials") == 0) { strcpy( storedMI, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes char err[150] = "PN0024!W!possible PN duplicate. Middle Initial is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, " Stored Middle Initial : "); strcat( err, storedMI ); strcat( err, " Input Middle Initial : "); strcat( err, strMI ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); ldap_value_free( vals ); ldap_memfree( a ); } // end of for looping through the entries - go to for loop top to get next entry } } return retVal; } //3125-CheckForPersonExistenceWithLastNameWildCard int CAssignPNObject::CheckForPersonExistenceWithLastNameWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedLN[31] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")(givenName="); strcat( strFilter, strFN); if ( strcmp( strMI, "") != 0 && strcmp( strMI, "") != 0 ) { strcat( strFilter, ")(initials="); strcat( strFilter, strMI); } strcat( strFilter, ")(surname="); strcat( strFilter, "*"); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable LN=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "sn") == 0) { strcpy( storedLN, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes char err[150] = "PN0026!W!possible PN duplicate. Last Name is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, " Stored Last Name : "); strcat( err, storedLN ); strcat( err, " Input Last Name : "); strcat( err, strLN ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); ldap_value_free( vals ); ldap_memfree( a ); } // end of for looping through the entries - go to for loop top to get next entry } } return retVal; } //3126-CheckForPersonExistenceWithBirthDateWildCard int CAssignPNObject::CheckForPersonExistenceWithBirthDateWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedBD[10] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")(givenName="); strcat( strFilter, strFN); if ( strcmp( strMI, "") != 0 && strcmp( strMI, "") != 0 ) { strcat( strFilter, ")(initials="); strcat( strFilter, strMI); } strcat( strFilter, ")(surname="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, strG); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, "*"); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable BD=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "bbBirthDate") == 0) { strcpy( storedBD, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes ldap_value_free( vals ); ldap_memfree( a ); char err[150] = "PN0027!W!possible PN duplicate. Birth date is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, " Stored Birth Date : "); strcat( err, storedBD ); strcat( err, " Input Birth Date : "); strcat( err, strBD ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); } // end of for looping through the entries - go to for loop top to get next entry } } return retVal; } //3127-CheckForPersonExistenceWithGenderWildCard int CAssignPNObject::CheckForPersonExistenceWithGenderWildCard( LDAP * ld, char* strSSN, char* strFN,char* strMI,char* strLN, char* strBD,char* strG,char* strFNI) { // To search for an entry based on all the non SSN arributes, we need a search filter that looks like //"(&(givenName=johnny)(initials=jj)(surname=johnson)(bbGender=M)(bbBirthDate=10/31/22))" char storedPN[9] = ""; char storedG[2] = ""; int retVal = 0; // LDAP Variables LDAPMessage *result, *e; BerElement *ber; char *a; char **vals; int rc, num_entries; char strFilter[200] = ""; strcat( strFilter, "(&(bbSsnCode="); strcat( strFilter, strSSN); strcat( strFilter, ")(givenName="); strcat( strFilter, strFN); if ( strcmp( strMI, "") != 0 && strcmp( strMI, "") != 0 ) { strcat( strFilter, ")(initials="); strcat( strFilter, strMI); } strcat( strFilter, ")(surname="); strcat( strFilter, strLN); strcat( strFilter, ")(bbGender="); strcat( strFilter, "*"); strcat( strFilter, ")(bbBirthDate="); strcat( strFilter, strBD); strcat( strFilter, "))"); rc = ldap_search_ext_s( ld, "ou=Person Number,o=Acme Inc,c=us", LDAP_SCOPE_SUBTREE, strFilter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if (rc != 0) { char err[150] = "PN0001!R!directory unavailable G=* Filter : "; strcat( err, strFilter); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); retVal = 12; } else { num_entries = ldap_count_entries( ld, result ); if (num_entries == 0) retVal = 0; else { retVal = 4; // got a close match but ret val is still 0 - just a warning // loop through each entry in the result set for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { // loop through each attribute in the entry. for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { // Save the relevant attributes in local variables if ((vals = ldap_get_values( ld, e, a)) != NULL ) { if (strcmp(a, "uid") == 0) { strcpy( storedPN, vals[0]); } if (strcmp(a, "bbGender") == 0) { strcpy( storedG, vals[0]); } } // end the loop through entry - one loop per attribute } // end of looping through the attributes ldap_value_free( vals ); ldap_memfree( a ); char err[150] = "PN0028!W!possible PN duplicate. Gender is only mismatch. Stored PN :"; strcat( err, storedPN ); // single value attribute : vals[0] strcat( err, " Stored Gender : "); strcat( err, storedG ); strcat( err, " Input Gender : "); strcat( err, strG ); m_msgQuantity ++; m_vecMsgs.push_back(CComBSTR(err)); } // end of for looping through the entries - go to for loop top to get next entry } } return retVal; } long CAssignPNObject::generatePersonNumber(char* ln) { // Create a person number // - Add the ASCII val of each character of the last name together // - Get system time and seed the random generator with it // - Get a random number and add it to the sum of chars from last name int decimal_spot, sign; char strNewVal[9] = ""; char * strVal = ""; long personNumber = 0; int lgth = strlen(ln); int sumOfLetters = 0; int randomVal; // get millisecs - next 3 lines int secsTime = 0; time_t ltime; time( <ime ); struct _timeb tstruct; secsTime = ltime; _ftime( &tstruct ); int millis = tstruct.millitm; for ( int i=0; i < lgth; i++) { sumOfLetters += (int)ln[i]; }; srand( millis ); randomVal = (int)((double)rand() / ((double)RAND_MAX + 1) * secsTime); randomVal = sumOfLetters + randomVal; strVal = ecvt (randomVal, 8, &decimal_spot, &sign); // convert val to a string int z = 0; for (i = 3; i < 8; i++, z++) strNewVal[z] = strVal[i]; for ( i = 0; i < 4; i++, z++) strNewVal[z] = strVal[i]; strNewVal[8] = '\0'; personNumber = atol(strVal); return personNumber; /* long personNumber = 0; int lgth = strlen(ln); int sumOfLetters = 0; int timeVal, randomVal; for ( int i=0; i < lgth; i++) { sumOfLetters += (int)ln[i]; }; timeVal = (unsigned)time(0); // 0 parm returns an int srand( timeVal ); randomVal = rand(); sumOfLetters = sumOfLetters + randomVal; personNumber = sumOfLetters + 70000000; return personNumber; */ } void CAssignPNObject::convertPNToString(long personNumber, char * strPersonNumber) { // We have a person number in the form of a long but we need it in string form int decimal_spot, sign; // These end up being throw aways char *pn; pn = ecvt (personNumber, 8, &decimal_spot, &sign) ; strcpy(strPersonNumber, pn); //return 0; } int CAssignPNObject::addEntry(LDAP* ld, char* newDN, LDAPMod* mods []) { // the ldap_add_ext_s returns a code indicating success or not // check it back in the calling function int rc; rc = ldap_add_ext_s( ld, newDN, mods, NULL, NULL ); return rc; }