// GetPassword.h #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifndef GetPasswordh #define GetPasswordh class CGetPassword { CString Password; CString Pattern; char PatternIdx; char GetAlNum() { for(;;) { char c=rand(); if((c> 0 )&&(c<= 9 )) return c+'0'; //This line gives numbers an equal chance of being picked as letters if((c> '0')&&(c<='9')) return c; //We could have just had this and the next line but we want to minimise rand() calls. if((c>='a')&&(c<='z')) return c; if((c>='A')&&(c<='Z')) return c; } } public: CGetPassword(char Length=9, int _PatternIdx=-1) { srand((unsigned)time(0)); New(Length, _PatternIdx); } CString GetPassword () const {return Password ;} CString GetPattern () const {return Pattern ;} int GetPatternIdx() const {return PatternIdx;} void SetPattern(int _PatternIdx=-1) { PatternIdx=_PatternIdx; #define PatternRows 12 static const char* Patterns[]={ "xXxXxXxXx", "XxXxXxXxX", "xxXxxXxxX", "XXxXXxXXx", "XXXxxxXXX", "xxxXXXxxx", "XXxxxxxxx", "XXXxxxxxx", "XXXXxxxxx", //Could have used more patterns like this "xxXXXXXXX", //But for a password of length 6 (for example) "xxxXXXXXX", // AAAAAAaaa is the same as AAAAAA which is no good! "xxxxXXXXX", // It is still possible to have all chars of one case because of numbers. }; if((PatternIdx<0) || (PatternIdx>PatternRows-1)) while(!(((PatternIdx=rand())>=0) && (PatternIdx<=PatternRows-1))); SetPattern(Patterns[PatternIdx]); } void SetPattern(const CString& _Pattern) { Pattern=_Pattern; const char* pat=Pattern; char* ptr=Password.GetBuffer(0); char b,c; while(c=*ptr) { if(!(b=*pat++)) break; *ptr++=(c>='0' && c<='9') ? c : (b & 0x20) | (c & ~0x20); //If it's a letter make the case the same as the pattern letter's case. } Password.ReleaseBuffer(); } void New(char Length=9, int _PatternIdx=-1) { PatternIdx=_PatternIdx; CString S(GetAlNum()); S+=GetAlNum(); #define RhymerRows 8 CString Rhymers[]={ "BCDEGPTV3", //Put longest first "N179", "AJK", "IY5", "QUW", "SX6", "H8",//only use these last two for Passwords of length 6 "R4",// - they are the only Passwords with only two rhyming characters. }; char c; //Don't use the last two Rhymers unless we have a Password length of 6: while(!(((c=rand())>=0) && (((Length==6)&&(c6)&&(c=0) && (c<=Rhyme.GetLength()-1))); //Pick one of Rhyme's characters S+=Rhyme.GetAt(c); //Append it to S if(c==0) Rhyme=Rhyme.Mid(c+1); //\ else if(c==Rhyme.GetLength()-1) Rhyme=Rhyme.Left(c); // >Remove the character from Rhyme else Rhyme=Rhyme.Left(c)+Rhyme.Mid(c+1); /// S+=GetAlNum(); S+=GetAlNum(); while(!(((c=rand())>=0) && (c<=Rhyme.GetLength()-1))); S+=Rhyme.GetAt(c); if(c==0) Rhyme=Rhyme.Mid(c+1); else if(c==Rhyme.GetLength()-1) Rhyme=Rhyme.Left(c); else Rhyme=Rhyme.Left(c)+Rhyme.Mid(c+1); if(Length==9) S+=GetAlNum(); if(Length>=8) S+=GetAlNum(); if(Length>=7) { while(!(((c=rand())>=0) && (c<=Rhyme.GetLength()-1))); S+=Rhyme.GetAt(c); } Password=S; SetPattern(PatternIdx); } }; #endif //ndef GetPasswordh