WISHLIST / TODO:
Add merging support to COMCollection.
Add the ability to load COMCollection from arrays in various ways.
Add the ability to export COMCollection to an array.
Change CCacheNode to inherit from CAVLTreeNode and not instantiate a new
object for it.
Figure out why COMCollection is leaking memory when IIS exits instead of
emptying itself as it is designed to do.
VERSION 8.0.0.0
Changed the license from the LAF LGPL to the GNU LGPL.
Fixed a small problem in CMutexQueue::~CMutexQueue that could cause an
access violation while destroying an exclusively locked lock.
VERSION 7.1.1.0 - 8/25/2004
Changed CMutexQueue::set_spinlock_sleep_msecs() to pass the new sleep time
value to big_lock_lock() when trying to lock the internal lock. Otherwise,
if the first attempt to use the lock is to set the sleep time and the
big lock fails, the big_lock_lock() will spin forever. Duh.
Changed a number of places in CMutexQueue that assumed a thread ID was a
simple type like an int. In Mac OS X, it is a pointer and direct
equality comparisons are meaningless.
Fixed a bug in CMutexQueue::clean_nodes() that was passing NULL to
pthread_getschedparam() in place of two pass-by-reference
parameters. Linux's pthread library will ignore the NULL parameters
but Mac OS X's pthread library will not -- it produces bus errors
instead.
VERSION 7.1.0.0 - 9/2/2003
Changed CMutexQueue::get_queue_size() and CMutexQueue::get_queue_status()
to optionally accept a parameter to make their lock attempts time out
after a number of milliseconds.
Fixed CMutexQueue::unlock() to honor the ignore_thread_ownership flag on
non-exclusive locks by finding the first lock and unlocking it.
This only makes sense when all of the threads using the lock have locked
without thread ownership.
Added CMutexQueue::set_user_data() and CMutexQueue::get_user_data() to allow
the mutex to hold one piece of user-specified data. This data is protected
from simultaneous updates by the mutex's internal lock but accesses are
not guaranteed to be first-come-first-served as with the lock()/unlock()
requests.
Added a new version of CMutexQueue::get_queue_size() that returns a
return_code value.
Changed most of the functions in CMutexQueue so they first check to see if
the destruct_pending flag is set and abort if it is.
Added a new class, LAF_semaphore, to provide a simple thread-safe semaphore
utility. It also provides a get_/set_user_data() feature like
CMutexQueue.
VERSION 7.0.0.0 - 8/19/2003
Changed CMutexQueue::big_lock_lock() so it will make a weak attempt to
discover if its internal state is valid and will also optionally watch for
the timeout to expire while spinning. This may help locate the cause of
some out-of-control thread symptoms that have been seen in production
(caused by other bugs but manifested in big_lock_lock()).
Fixed a nasty little bug in CMutexQueue::unlock() that could cause access
violations under certain conditions.
Changed CMutexQueue::lock() and CMutexQueue::upgrade() so they will clean
out stale locks held by threads that have exited without releasing their
locks.
Added a third parameter to CMutexQueue::lock() to be set by threads that are
grabbing locks that must remain locked even if the thread dies. The new
parameter sets a flag on the lock that prevents it from being broken
when the thread exits. This is necessary for locks that function as delay
timers for worker threads. This change breaks backwards compatibility.
VERSION 6.9.0.0 - 6/25/2003
Added validation types "time" and "hhmm" to form_validations.js, along with
some conversion routines.
Changed validate_isEmail() in form_validations.js to allow dots ('.') in
email addresses. According to RFC 822, they're not legal but so many ISPs
and companies use them that they've got to be able to pass the form
validation.
Changed case_sensitive_compare_variant_ptrs(),
case_insensitive_compare_variant_ptrs(),
case_sensitive_compare_md_variant_ptrs() and
case_insensitive_compare_md_variant_ptrs() to attempt to compare their
parameters as numbers if strings cannot be extracted from them. This
allows CMisc::Quicksort() to sort arrays of numbers instead of just
strings. The results of sorting an array of mixed types (strings and
numbers) is undefined.
VERSION 6.8.0.0 - 3/28/2003
Added GetDATEFromVariant() to reusables_atlcom.*.
VERSION 6.7.0.0 - 3/13/2003
Added the "money" type to form_validations.js to validate dollar currency
fields.
Fixed validate_isFloat() and validate_isInteger() in form_validations.js
to correctly validate numbers with commas.
Fixed validate_isEmail() in form_validations.js to correctly validate email
addresses.
Added an overloaded version of CAVLTree::remove() that will take one
parameter, a CAVLTreeNode*, and remove it from the tree if it is found.
VERSION 6.6.2.0 - 2/12/2003
Fixed a problem in CSMTP::CSMTPQueue::run_queue() that was causing multiple
asynchronous threads to consume all available CPU while waiting for the
queue mutex to unlock. There was no sleep() command issued when the
call to upgrade() failed; the thread would just retry upgrade() as fast
as possible.
VERSION 6.6.1.0 - 1/6/2003
Changed CObjectPool::get_object() to run any newly created objects through
the check_object (or check_object_with_return) function before returning
it.
Changed validate_isEmail() in form_validations.js to allow quoted usernames
in email addresses and disallow special characters outside of quoted
usernames.
Added new parameters to validate_checkone() and validate_checkall() to allow
the caller to specify if select() and focus() are to be called on the input
element if it fails validation. This can be important when the form has
onFocus() or onBlur() handlers.
VERSION 6.6.0.0 - 10/23/2002
Added the ability to CMisc::Quicksort to sort two-dimensional arrays. It
now takes two additional (optional) parameters, the sort dimension and
the sort index.
Removed a contradictory copyright notification from the top of
form_validations.js.
VERSION 6.5.7.0 - 9/24/2002
Fixed a critical bug in CMutexQueue::upgrade() -- if an upgrade attempt
failed, upgrade() was not relocking with nonexclusive access. Also, if
the upgrade attempt times out and another thread has called upgrade()
after the timed out thread did, relocking with nonexclusive access is not
possible (it would require more waiting). In that case, the lock has been
broken and the caller must not call unlock().
Changed CMutexQueue::unlock() to take no action if the caller is not one of
the current lock holders. This is to help deal with the issue of a failed
upgrade() attempt that broke the lock where the caller attempts to unlock()
anyway. unlock() now accepts a parameter that will override the caller
checking and force the unlock of another thread's lock. This is usually
only important if CMutexQueue is being used to control worker thread
sleeps (mercifully rare). Everybody else should not notice this change.
Removed some debugging code from CComCollection and core files.
VERSION 6.5.6.0 - 9/18/2002
Marked CAVLTree::~CAVLTree(), CCache::~CCache(), CCache::~CCacheNode(),
CHeap::~CHeap(), CObjectPool::~CObjectPool() and CStack::~CStack()
virtual to force decendant classes' destructors to fire when the objects
are deleted. This closes a number of memory leaks observed in production,
both in LAFcommon and in other projects.
Added CCacheNode::empty() and changed CCacheNode::~CCacheNode() to call it.
This will allow derived classes' destructors to also clean up the
CCacheNode structure.
Changed CCOMCollection::CCOMCollectionSharedNode::~CCOMCollectionSharedNode()
to call CCacheNode::empty().
Added CHeap::empty() and changed CHeap::~CHeap() to call it. This will allow
derived classes' destructors to also clean up the CHeap structure.
VERSION 6.5.5.0 - 9/11/2002
Fixed two serious errors in CMutexQueue::unlock() and
CMutexQueue::downgrade() caught by BoundsChecker that could put the node
pointed to by newest_node into the saved_nodes list. This allowed
the node (or other newer nodes) to be freed by another function when they
are still in use by CMutexQueue::lock() or CMutexQueue::upgrade().
Fixed generate_guid(), generate_short_guid() and generate_nonsequential_id()
to return NULL if any of the Win32 RPC functions return a non-success code.
Extended CObjectPool to allow the functions provided by the caller to accept
an additional parameter of void** through which they may return additional
information. Since CObjectPool is most often used for database connection
pools, this provides a way to pass back exception messages.
VERSION 6.5.4.0 - NOT RELEASED
Fixed cgi_variable_append() to behave correctly when there is no data to be
read from stdin -- fread on Win32 blocks when given a format of "%0c" and
there is no available data.
Removed some illogical cruft from CMutexQueue::upgrade().
VERSION 6.5.3.0 - 8/7/2002
Fixed a set of typos in form_validations.js that was preventing the correct
validation of credit card numbers.
Fixed cgi_variable_append() to make it possible to correctly retrieve POSTed
variables in CGI scripts.
Fixed some of the #include directives in the reusables files so they will
compile in non-MFC Win32 projects.
VERSION 6.5.2.0 - 6/27/2002
Fixed the CMutexQueue::~CMutexQueue so its new thread accounting system will
also unlock dead exclusively locked threads.
VERSION 6.5.1.0 - 6/25/2002
Changed CMutexQueue::lock() slightly to return fail_destruct_pending to
callers who were waiting on a queue and whose turn had come up when
the queue was marked for destruction.
Changed form_validations.js to ignore invalid form element objects.
Reworked some of CMutexQueue's internal data structures to perform better
accounting of which threads are waiting on locks. This allows the
CMutexQueue destructor to check if the waiting threads are still active
before allowing the queue destruction to complete. This is necessary
because some execution environments kill all the threads without notifying
them properly so they can clean up their resources. Thanks a lot, Sun!
Changed CMutexQueue to use nanosleep() instead of sched_yield() under Linux
because nanosleep() actually yields the remainder of the thread's timeslice
while sched_yield() does not (according to Ed Bradford @ IBM).
VERSION 6.5.0.0 - 6/3/2002
Added a new function to form_validations.js to allow a known element's
validation properties to be updated named validate_updateelement().
Moved the documentation out of form_validations.js into
form_validations_docs.txt because the size was becoming significant.
Changed the types "datetime", "mssqldatetime" and "cdatetime" in
form_validations.js to not require a time but to assume midnight if no
time is given.
VERSION 6.4.0.0 - 5/15/2002
Changed validate_checkall() in form_validations.js to optionally accept an
additional argument: the form object to check. If the argument is given,
only the form elements contained by the form object will be validated.
This is necessary for a page that contains multiple, unrelated forms that
require validation.
Added reusables_CGI.* to provide some basic CGI input handling routines.
Fixed several serious errors in reusables_ObjectPool.cpp that were using
CMutexQueue locks without timeouts and always assuming that the object
creation function would succeed without checking its returned value. These
bugs could cause deadlocks or access violations in database connection
pools if attempts to create new connections failed for any reason.
Fixed a #define problem in reusables_MutexQueue.h so it will compile under
Linux.
VERSION 6.3.2.0 - 4/9/2002
Changed html_canonicalize() and html_canonicalize_no_break() to not replace
"|" with "¦" because "¦" does not display as the correct
character in any browser. It instead displays a vertical bar with a
different ASCII code that is illegal in javascript code.
VERSION 6.3.1.0 - 4/8/2002
Changed javascript_canonicalize(), html_canonicalize() and
html_canonicalize_no_break() not to replace unprintable characters with '?'
since every ASCII character is allowed or replaced.
Fixed javascript_canonicalize() to handle a NULL source string without
generating an access violation.
VERSION 6.3.0.0 - 4/3/2002
Added a parameter to GetBSTRFromString() to allow the caller to specify the
length of the input string, in case it contains embedded nulls.
VERSION 6.2.0.0 - 3/20/2002
Added the field types "cdate" and "cdatetime" to form_validations.js to check
values that are to be converted to time_t values.
Changed GetTimeTFromDATE() to check the converted value against the bounds of
time_t. CTime::CTime() asserts when asked to deal with a date value that
is out of bounds for time_t.
VERSION 6.1.1.0 - 3/14/2002
Fixed sql_canonicalize_like() to do more than throw access violations.
Add GetTimeTFromVariant() to reusables_atlcom.*.
VERSION 6.1.0.0 - 3/12/2002
Fixed identical typos in validate_isVisa(), validate_isMasterCard(),
validate_isAmericanExpress(), validate_isDinersClub(),
validate_isDiscover() and validate_isJCB() in form_validations.js.
Added a #include directive to reusables_guid.h to provide a definition for
NULL.
Fixed replace_text() in reusables_c.cpp to correctly handle a NULL source.
Added sql_canonicalize_like() to reusables_c.cpp to canonicalize strings for
SQL LIKE clauses.
VERSION 6.0.0.0 - 2/12/2002
Added putref_Item() to CCOMCollection. Apparently a property cannot accept
an object reference without being declared as "propputref" in the IDL file.
All along, LAFcommon.COMCollection has been unable to store COM objects
because its Item property didn't have a "propputref" version. I've managed
figured out the reasons behind most of IDL's braindamagedness, but this one
is beyond me. The only way to accept an object reference through COM is
by using a VARIANT (IObject*s don't count as references). VARIANTs are
accepted by "propput" properties as long as they don't contain object
references. WHAT'S THE DIFFERENCE? A VARIANT's a VARIANT's a VARIANT!
This is just stupid.
Changed the behavior of GetEmptyFromVariant() not to use VariantChangeType()
to coerce VARIANTs of types VT_UNKNOWN, VT_DISPATCH, VT_BYREF|VT_UNKNOWN or
VT_BYREF|VT_DISPATCH to VT_EMPTY. Apparently, anything is coercable to
VT_EMPTY and VariantChangeType() just sets the destination VARIANT VT_EMPTY
instead of running the Value property of the referenced object.
Unfortunately, GetEmptyFromVariant() is used in a great number of places,
so it may take a while to ensure this change does the Right Thing.
VERSION 5.4.3.0 - 12/18/2001
Fixed a serious problem in CAVLTree::insert(CAVLTreeNode*) that was not
clearing the avl_children array or resetting the avl_height field. This is
an issue when the node has been inserted into a CAVLTree object in the past
and its child pointers are not NULL and its height is not 0. This can
cause anything from infinite loops to access violations.
VERSION 5.4.2.0 - 12/12/2001
Added GetUnsignedCharFromVariant() to reusables_atlcom.* to get an unsigned
char from a VARIANT.
VERSION 5.4.1.0 - 12/10/2001
Removed all of the "helpstring" entries from the IDL file. The typelib is a
stupid place to store documentation and comments like "property Name"
and "method Save" don't help anyone anyway. Removing the strings reduced
the size of the DLL by 4096 bytes.
Changed email.asp and flash_email.asp to accept multiple target email
addresses.
Changed flash_email.asp to perform marker substitution in the subject line
and accept "apparently from" and "apparently to" information like
email.asp.
VERSION 5.4.0.0 - 11/26/2001
Added the value disabled_for_destruct to CMutexQueue::mutex_statii to allow
a caller to determine if the queue has been disabled without having to
attempt to lock it.
VERSION 5.3.7.0 - 11/19/2001
Changed the list of targets and replacements in html_canonicalize() and
html_canonicalize_no_break() to replace all "extended" ASCII characters
with their HTML encoding instead of a question mark. This should fix
the problem of cut-n-pasted text from MS Word that contains "smart
quotes" showing up full of question marks.
VERSION 5.3.6.0 - 11/16/2001
Fixed a serious problem with CMutexQueue::~CMutexQueue that was causing
access violations when the mutex queue was destroyed while still
locked and waiting for the locks to be released.
Fixed a problem with CMutexQueue::~CMutexQueue that wasn't releasing the
queue's big lock, causing any new attempts that began before the object's
destruction was complete to stall while trying to lock the queue's big
lock.
Fixed CMutexQueue::lock() to honor the destruct_pending flag even when
spinning on the lock isn't necessary.
Changed CMutexQueue::lock() and CMutexQueue::unlock() to make the default
timeout -1 msecs instead of 0. A timeout of 0 msecs now indicates no
wait at all and provides a fast path if the lock/upgrade attempt is
unsuccessful (no sleeping).
Added set_max_queue_size() and set_spinlock_sleep_msecs() to CMutexQueue
to allow the maximum queue size and the spinlock sleep time to be set
outside the constructor.
Fixed CSMTP::CSMTPQueue::generate_script() to encode messages slightly
differently. Instead of trying to encode into quoted-printable format
and replace lone periods with double periods (..) in the same pass, two
passes are now performed. This is necessary because encoding into
quoted-printable may word-wrap a period onto its own line. However,
because replace_text() regards the line break as part of the previous
replacement, it does not notice the lone period and does not replace it.
This was causing the SMTP server to return error codes when the message
appeared to end prematurely. This bug was discovered by Lonnie Pryor.
Replaced all instances of AfxBeginThread() with _beginthread(). After
reading online (and much debugging within LAFspam), AfxBeginThread()
uses the MFC library to start and control its threads. _beginthread()
uses the CRT (C RunTime). Thus, AfxBeginThread() requires the both MFC
library and the multithreaded C library while _beginthread() requires
only the multithreaded C library. If MFC is not active/available when
AfxBeginThread() is called, the process hangs. If the multithreaded
C library is not available when _beginthread() is called, an error is
returned.
VERSION 5.3.5.0 - 11/8/2001
Fixed potential problems in base64_decode(), generate_guid(),
CAVLTree::absorb() and CAVLTree::traverse_postorder() where the return
variable could be returned without its value having been set.
Fixed a potential problem in replace_text() where next_match_num could be
used without having been initialized.
Fixed a potential problem in quicksort() where pivot_element could be used
without having been initialized.
VERSION 5.3.4.0 - 10/25/2001
Cleaned up CAutoArray's constructors.
Fixed CAutoArray so it will compile under Linux.
Fixed CCache so it will compile under Linux without warnings.
Cleaned up CObjectPool's constructors.
Fixed CObjectPool so it will compile under Linux.
Cleaned up CQueue's constructors.
Fixed CQueue so it will compile under Linux.
Fixed reusables_guid.* so it will compile under Linux.
Fixed CSMTP so it will work under Linux.
VERSION 5.3.3.0 - 10/15/2001
Changed email.asp and flash_email.asp to send their mail through
smtp-script.lookandfeel.com by default instead of email.lookandfeel.com.
Changed flash_email.asp to URL encode all the text in its response and not
to place a line break before the first response character.
Fixed GetBSTRFromString() to use malloc() instead of _alloca() when the
source string passes a #defined threshhold. Using _alloca()
unconditionally was causing stack overflows with large strings.
VERSION 5.3.2.0 - 10/11/2001
Fixed a(nother) bug in replace_text() that was introduced in version 5.1.0.0:
if the shortest target is the same length as the longest replacement, the
space allocated for the destination string is one character too short.
Fixed a bug in replace_text() that has existed since was first written: if
the source string is shorter than the shortest target and the shortest
target is shorter than the longest replacement, only one byte will be
allocated for the destination string.
Increased the time CSMTP will wait for an SMTP server response during mail
delivery to better cope with slow/overloaded servers.
VERSION 5.3.1.0 - 10/8/2001
Cleaned up reusables_c.* to make it compile under Linux.
Cleaned up reusables_MutexQueue.* to make it compile under Linux.
Fixed LAFCOMMON_SMTP_NAMES_ACCOUNTABILITY_CODES and
LAFCOMMON_SMTP_VALUES_ACCOUNTABILITY_CODES in reusables_SMTP.cpp so
CSMTP::constant2value() will find accountability code names correctly.
VERSION 5.3.0.0 - 9/13/2001
Included limits.h from reusables_MutexQueue.h so it would compile when
included in other projects.
Added CMutexQueue::disable_for_destruct() to allow a caller to announce its
intention to destroy the queue so new lock attempts will fail and return
CMutexQueue::fail_destruct_pending.
Changed all the uses of CopyMemory() in reusables_SMTP.cpp to memcpy().
Added the macro definitions REUSABLES_GUID_STRLEN_GUID,
REUSABLES_GUID_STRLEN_SHORT_GUID and REUSABLES_GUID_STRLEN_NONSEQUENTIAL_ID
to reusables_Guid.h to remove any assumptions about the length of strings
returned from the GUID functions.
Cleaned up CHeap's constructors.
Fixed a potential bug in CHeap::init_heap that would try to dynamically
allocate 0 bytes of memory.
Changed replace_text() in reusables_c.* to accept a pre-declared buffer
area to store its result into rather than unconditionally declaring its
own.
Changed generate_guid(), generate_short_guid(), generate_nonsequential_id(),
convert_short_guid_to_guid(), convert_guid_to_short_guid() to accept a
pointer to a previously allocated memory area in which to store the result
instead of unconditionally allocating new memory.
Fixed matching bugs in CMutexQueue::lock() and CMutexQueue::upgrade() that
could potentially gain a lock and timeout without realizing the lock had
been aquired. The code was also slightly restructured and simplified.
Fixed a serious error in CMutexQueue::upgrade() that would correctly upgrade
the lock but would not update the newest_node pointer if the thread was
forced to wait on the upgrade. If a call to CMutexQueue::lock() came while
the upgrade()ing thread was waiting, the stack would be corrupted and the
upgrade()ing thread would deadlock forever (or timeout).
Declared CAVLTreeNode::~CAVLTreeNode() as a virtual function so it would be
correctly overridden by inheriting classes.
VERSION 5.2.4.0 - 8/15/2001
Fixed the comment blocks at the top of form_validations.js, email.asp and
flash_email.asp to format them correctly for the respective language so
they wouldn't generate errors.
Changed GetEmptyFromVariant(), GetErrorFromVariant(), GetBSTRFromVariant(),
GetStringFromBSTR(), GetStringFromVariant(), GetNumberFromVariant(),
GetNumberTypeFromVariant(), GetObjectFromVariant(), GetArrayFromVariant(),
GetArrayTypeFromVariant(), GetBooleanFromVariant(),
GetDateTimeFromVariant(), GetBSTRFromString(), GetDATEFromTimeT() and
GetTimeTFromDATE() to fail gracefully if passed a NULL pointer.
VERSION 5.2.3.0 - 8/6/2001
Fixed replace_text() again so it would not throw an access violation
whenever it is called with a set of targets of which some are substrings
of others. Fortunately, replace_text() isn't very big, so there can't
be many more "I.R. Baboon"-quality bugs left in it.
VERSION 5.2.2.0 - 8/5/2001
Fixed replace_text() in reusables_c.cpp so it would not throw an access
violation whenever it was called with multiple targets (as in
html_canonicalize()). This bug was introduced in version 5.1.0.0.
Made minor revisions to the documentation for SMTPMail.
VERSION 5.2.1.0 - 7/31/2001
Added a copyright block to the top of all the source files and packaged
LAFcommon for distribution as free software!
Changed sql_canonicalize()'s second parameter to default to NULL so it will
not break backwards-compatibility.
Added a second parameter to html_canonicalize() and javascript_canonicalize()
so they too can return the length of the returned string. The parameters
are NULL by default.
Added third parameters to all versions of GetStringFromBSTR() and
GetStringFromVariant() so they can return the length of the returned
string. The parameters are NULL by default.
Changed both versions of GetStringFromVariant() to call GetStringFromBSTR()
internally instead of duplicating the code inside themselves.
Changed CHTMLUtil::canonicalize(), CHTMLUtil::canonicalize_no_break(),
CJavascriptUtil::canonicalize() and CSQLUtil::canonicalize() to remove
their use of CStrings in favor of char*s. They now call the functions in
reusables_c.* instead of reusables_mfc.*.
Changed javascript_canonicalize(), html_canonicalize(),
html_canonicalize_no_break() and sql_canonicalize() in reusables_atlcom.cpp
to call their non-CString-based counterparts from reusables_c.*. This was
done to improve the performance and to unify their behavior behind the
common name.
Changed CMisc::ByteArray2String() to use char*s instead of CStrings.
Changed CPAM::authenticateUser() to use char*s instead of CStrings.
Cleaned up CPAM::authenticateUser() slightly to remove useless database
status checks.
Added GetTimeTFromDATE() and GetDATEFromTimeT() to reusables_atlcom.* to
provide the ability to convert between DATEs and time_ts since that
procedure is non-obvious.
Added the "Win32 Release MinDependency" build configuration.
VERSION 5.2.0.0 - 7/11/2001
Added an overloaded version of GetBooleanFromVariant() to reusables_atlcom.*
that accepts a parameter of type VARIANT_BOOL* instead of BOOL*. When
working in COM, VARIANT_BOOL is the correct type to use, though (in this
version, anyway) the compiler is kind enough to upcast to BOOL when needed.
Changed the old version of GetBooleanFromVariant() to simply call the new one
and correctly convert the result from VARIANT_BOOL to BOOL.
Added convert_short_guid_to_guid() and convert_guid_to_short_guid() to
reusables_guid.* to provide a way to convert between the two GUID formats.
Added ConvertShortGuidToGuid() and ConvertGuidToShortGuid() to CMisc to
expose convert_short_guid_to_guid() and convert_guid_to_short_guid()
(respectively) through COM.
VERSION 5.1.0.0 - 7/6/2001
Cleaned up CStack's constructors.
Added GetObjectFromVariant() to reusables_atlcom.* to assist in extracting
IUnknown*s from VARIANTs passed through COM.
Moved the initialization code out of CObjectPool::CObjectPool() into a new
function named CObjectPool::init() and changed CObjectPool::CObjectPool()
to call CObjectPool::init(). Also moved the pool emptying code out of
CObjectPool::~CObjectPool() into a new function named CObjectPool::empty()
and changed CObjectPool::~CObjectPool() to call CObjectPool::empty().
These two changes were made to allow CObjectPool to be instantiated through
calls to malloc()/calloc()/realloc() and released through calls to free().
Corrected a very serious problem in CMutexQueue::lock() that was changing
internal data structures without holding the big queue lock. It appears as
though the big queue locking code was removed by mistake when the timeout
code was added in version 4.3.0.0.
Changed CMutexQueue to make the spinlock delay configurable. It defaults to
100 msecs if no value is given during object construction.
Changed CMutexQueue to limit the number of threads permitted to wait on the
lock. If the limit is reached, additional lock attempts will fail with
error_queue_too_large. If no value is given during object construction,
queue size is unlimited. NOTE: This change only affects
CMutexQueue::lock() -- upgrading or downgrading a lock does not impact the
queue size.
Changed the semantic meaning of CMutexQueue::get_queue_size() to return the
number of threads currently waiting on the queue. Previously, it had
indicated the number of nodes in the wait queue, which is not particularly
useful to an external caller.
Added CMutexQueue::get_queue_status() to allow a caller to determine if the
queue is locked and if so, if it is exclusively or nonexclusively locked.
This is only useful in a very limited number of situations because the
queue status could change while the call to CMutexQueue::get_queue_status()
is returning, but it provides more information than
CMutexQueue::get_queue_size() alone can give.
Cleaned up CObjectPool's constructors.
Changed generate_nonsequential_id() to append "-ID" to the IDs instead of
prepending it. This should speed up string-based comparisons slightly.
This does not present a backwards-compatibility issue because nonsequential
IDs are not stored persistantly and the new format has the same length as
the old one.
Changed generate_guid(), generate_short_guid() and
generate_nonsequential_id() to accept a parameter that indicates if they
should use malloc() or the C++ "new" operator. The default behavior is
to use "new".
Added an overloaded version of sql_canonicalize() that will accept a
printf()-style format and a variable list of field values, canonicalize
the string values, sprintf() the whole thing together and return the
result. This function doesn't add efficiency so much as it adds simplicity
for the caller.
Rewrote a significant portion of replace_text() to be a little smarter about
its string management -- using strcat() on long string is very inefficient.
It was also running strstr() on the source string every time it was looking
for a new target to replace, which meant running strstr() m*(n-1) extra
times (where n is the number of targets and m is the number of total
replacements needed). The changes should significantly improve
performance.
Added a new parameter to replace_text() and sql_canonicalize() to return the
length of the result string so the caller does not immediately have to run
strlen() on it. The parameter has a default value of NULL.
VERSION 5.0.2.0 - 6/21/2001
Fixed CSMTP::CSMTPQueue::canonicalize_message() to correct a bug noticed by
Lonnie Pryor -- HTML message sections were being incorrectly encoded when
a character was being replaced by its hexadecimal representation and the
line-wrapping sequence was forcing a line break in the middle of the
encoded sequence. CSMTP::CSMTPQueue::canonicalize_message() now includes
the concept of "unbreakable sequences" to prevent this from happening.
VERSION 5.0.1.0 - 6/18/2001
Changed MUTEXQUEUE_SPINLOCK_DELAY_MSECS in reusables_MutexQueue.h to 100
instead of 0 -- the lock contention between threads was so fierce that
time-dependent protected functions (like database accesses) were being
resource-starved and were timing out because other threads were spinning
so fast on the held lock. NOTE: This change only imposes a delay on the
loop that waits for the lock to become available. If a thread can aquire
the lock without having to spin, the delay will not be imposed.
VERSION 5.0.0.0 - 6/18/2001
Changed generate_short_guid() to reverse the nibbles of the first four
bytes of the GUID in order to put the least significant bits of the first
four bytes first -- they are the ones that change the fastest, so textual
comparisons of the new short GUID format will spot differences faster.
This format change breaks backwards compatibility, but fortunately the
only place short GUIDs are being saved persistantly are in the Americo
reports database, which will be converted to the new format.
Fixed several serious bugs in CMutexQueue::lock() and CMutexQueue::upgrade()
that would access protected data members without holding the queue lock
and that would not decrement the reference count when a non-exclusive lock
attempt timed out.
Changed CMutexQueue::~CMutexQueue() to allow the caller to hold an exclusive
lock when the destructor fires. All threads attempting to gain the lock
when the destructor fires will return fail_destruct_pending.
VERSION 4.3.0.0 - 6/7/2001
Added timeout capability to CMutexQueue::lock() and CMutexQueue::upgrade()
to allow the caller to specify the maximum amount of time to wait on
a lock request. NOTE: This timeout system uses GetTickCount(), which is
only as precise as the system timer. According to the documentation,
the system timer in Win95 and above has a resolution of approximately
55 ms.
VERSION 4.2.0.0 - 5/21/2001
Fixed an ASP syntax error in flash_email.asp.
Added the ability to specify a faux sender and faux recipient in email.asp
through CSMTP::process_message()'s apparently_from and apparently_to
parameters.
Added base64_decode() to reusables_c.* to decode "Base64" encoded strings
used in MIME encodings and to transmit the username and password entered
by the user in a web browser for Basic Authentication.
Changed VersionInfo() in CCOMCollection, CHTMLUtil, CJavascriptUtil, CMisc,
CPAM, CSendmail, CSMTPMail and CSQLUtil to accept VARIANT* parameters
instead of short* parameters. ASP correctly sees short* parameters as
"ByRef Integer", but it turns out to be impossible to pass a parameter in
a way that does not generate a type mismatch error. This does not break
backwards compatibility since there is no way VersionInfo() could be in
use anywhere.
Added the element types "zip", "uszip" and "canadianzip" to
form_validations.js to validate ZIP code fields.
Added reusables_MutexQueue.* to provide a general-purpose locking mechanism
for uses that must distinguish between read-only and read/write access.
CMutexQueue assumes that all non-exclusive accesses may occur
simultaneously while exclusive accesses must occur in order. To this end,
it implements a queue structure that keeps requests grouped as
exclusive or non-exclusive and in FIFO order. While a non-exclusive lock
is held, any new non-exclusive locking requests are granted immediate
access. All exclusive lock requests are queued in FIFO order and block
until the lock requests queued prior are granted and released. Once the
queue begins to fill, any new requests are grouped by type and queued. For
instance, if three non-exclusive lock requests are made, all three are
granted. If two exclusive lock requests are made, followed by four
non-exclusive requests, they are queued in order until the three
non-exclusive locks are released, at which point the first exclusive lock
is granted. When it is released, the second exclusive lock is granted.
When it is released, the four non-exclusive locks are granted
simultaneously. Queue size is limited only by available memory. NOTE:
CMutexQueue makes it very easy for a thread to deadlock itself if it
requests several locks at once.
Changed CCOMCollection::CCOMCollectionSharedNode, CCache, CMisc, CPAM,
CObjectPool and CSMTP to use CMutexQueue instead of CMutex. In addition
to a performance win, this also cleans up some of the wierd spinlocking
code that was adequate but used the "quick draw" (random) technique of
lock ordering instead of "first come, first served".
Fixed a problem in CSMTP::CSMTPQueue::deliver_message() that would ignore
an accountability that included CSMTP::process_batch_attempt_all if
max_recipients_per_message were set to 1 or if the last recipient in the
script were rejected. Now the CSMTP::process_batch_attempt_all
accountability will only be ignored if only one addressee is given.
Added the capability to perform form field substitutions in an email's
subject line to email.asp.
Fixed email.asp to correctly handle incomplete form field markers.
VERSION 4.1.1.0 - 4/13/2001
Changed CSMTP, CSMTPMessage, CSMTPQueue and CSMTPQueuePool to use malloc()/
free() instead of new/delete whenever possible to allow the use of
realloc() for massively repetitive procedures where a lot of memory is
being allocated and freed (e.g. CSMTPQueue::generate_script()).
Fixed several potential buffer overruns in CSMTP, CSMTPMessage, CSMTPQueue
and CSMTPQueuePool where insufficent space was being allocated to store
data.
Fixed several instances in CSMTP, CSMTPMessage, CSMTPQueue and CSMTPQueuePool
where the memory allocation scheme was inconsistant (i.e. memory was being
allocated with new but deallocated with free()).
Changed CSMTP::CSMTPQueue::generate_script() to use realloc() while creating
new recipient scripts to avoid repeatedly deallocating and reallocating
potentially large memory areas.
VERSION 4.1.0.0 - 3/27/2001
Changed CSMTP's accountability values to support bitwise ORed values to
produce more combinations and achieve the desired behavior. The biggest
change is to force the delivery system to attempt delivery to all
recipients on a message that has many recipients, even if one or more of
the addresses are rejected by the server
(CSMTP::process_batch_attempt_all).
Added partial accountability support to CSMTP.
VERSION 4.0.0.0 - 3/22/2001
(sigh) Added a(nother) warning message to the tops of email.asp,
flash_email.asp, form_validations.js and lafcommon_vbs.txt to tell others
not to copy those files into their projects but to access them from the
"/LAFcommon" virtual directory.
Fixed syntax errors in lafcommon_vbs.txt and email.asp found by Todd Gambal.
Changed CCOMCollection::put_CaseSensitive() to require that the current
collection must be empty before case sensitivity can be changed. This
breaks backwards-compatibility, so a major version number change is
required.
Changed CCOMCollection::get_NamedConstant() to accept a long* instead of an
EnumCOMCollectionReturnCodes* because it is intended to translate more
than just return codes. This should not break backwards-compatibility.
Added complete documentation of the LAFcommon.COMCollection interface.
Moved the contents of COMCollectionNode.* and COMCollectionSharedNode.* into
COMCollection.*.
Moved the classes CCOMCollectionNode and CCOMCollectionSharedNode inside the
CCOMCollection class.
VERSION 3.0.0.0 - 3/6/2001
Changed email.asp and flash_email.asp to use SMTPmail instead of Sendmail.
Removed all usage of CStrings from CCOMCollection, CCOMCollectionNode and
CCOMCollectionSharedNode.
Defined EnumCOMCollectionReturnCodes in LAFcommon.idl to provide a set of
return codes for CCOMCollection functions.
Changed the parameter types of CCOMCollection::get_CaseSensitive() and
CCOMCollection::put_CaseSensitive() from VARIANT to VARIANT_BOOL.
Changed the parameter type of CCOMCollection::Empty() from VARIANT to
EnumCOMCollectionReturnCodes.
Changed the parameter type of CCOMCollection::get_EnumerateKeys() and
CCOMCollection::put_EnumerateKeys() from VARIANT to VARIANT_BOOL.
Changed the parameter type of CCOMCollection::get__NewEnum() from VARIANT*
to IUnknown**.
Added the functions get_ThrowErrors(), put_ThrowErrors(), get_ErrorMessage()
and get_NamedConstant() to CCOMCollection to bring its COM interface into
line with the new LAF "standard" interface.
NOTE: None of the above parameter type changes should affect the use of the
LAFcommon.COMCollection interface from ASP; they'll actually help by
letting the ASP engine perform some of the type checking. It does break
any C++ projects that use LAFcommon.COMCollection through an imported type
library, hence the major version number increase. Thankfully, no such
projects exist (AFAIK).
Cleaned up the CCache and CCacheNode constructors.
Added the member variable cache_persist_secs to CCacheNode to allow each node
in the cache to have a different maximum idle time.
CCache::cache_default_persist_secs will only be used if
CCacheNode::cache_persist_secs is equal to 0.
Added LAFcommon.COMCollection.MaxIdleSecs() to expose the new
cache_persist_secs property via COM.
Renamed CCache::cache_secs to CCache::cache_default_persist_secs,
CCache::get_timeout() to CCache::get_default_expiration_time(),
CCache::set_timeout() to CCache::set_default_expiration_time() and
CCacheNode::cache_timestamp to CCacheNode::cache_expiration_time.
Changed the semantic meaning of the timestamp stored in CCacheNode. The
value now indicates the time at which the node will expire, not the time at
which the node was created.
VERSION 2.7.0.0 - 2/6/2001
Added set_return_path_address() to CSMTP to allow the caller to specify the
contents of the messages' "Return-Path" header field. This will allow
bounced messages to be returned to the correct address even though the
originator's address was hidden using the apparently_from parameter to
CSMTP::process_message().
Added the property LAFcommon.SMTPMail.ReturnPathAddress as an interface to
CSMTP::set_return_path_address().
Fixed a problem in CCache::compare_timestamps() that was not sorting the
CCacheNodes in the cache's heap in the correct order.
Fixed a problem in CHeap::find_node_index() that was incorrectly supposing
the heap was stored in-order and abandoning the search for a node when the
first node was found whose value was greater than the target value.
Because this often meant the target node was not found, nodes were deleted
from a cache's AVL tree without being removed from the heap when
CCache::remove() was called. If the node's memory space was then freed,
any reference to the node through the heap would result in an access
violation. This was most likely the cause of the Metabase crashes observed
in production.
VERSION 2.6.0.0 - 1/24/2000
Added the capability for generating "multipart/related" messages to CSMTP.
This means that a message can be sent out that displays its attachments,
without requiring the mail client to hit a remote server to display
images, for instance. Unfortunately, Microsoft Outlook is not RFC 2387-
compliant, so messages sent this way will not work correctly in that
environment. This is more completely documented in doc_SMTPMail.txt.
Added the section types plain_text_inline, html_text_inline,
text_file_inline, html_file_inline, binary_file_inline, gif_file_inline
and jpeg_file_inline to CSMTP::section_types to facilitate the
"multipart/related" message capability.
Added CSMTP::constant2value() and CSMTPMail::Constant2Value() to allow a
caller to translate a defined constant like CSMTP::success into its value
if access to the constants is not possible for some reason.
VERSION 2.5.3.0 -- 1/12/2001
Changed CMisc::SpawnProcessAsUser() to accept variants of type VT_EMPTY in
place of missing optional parameters to achieve the same effect as
leaving them out.
Changed enum CSMTP::accountability_codes to cover all possible uses/needs.
Since accountability hasn't been implemented yet, this shouldn't break
any backwards compatibility.
Changed CSMTP to use short GUIDs for all of its IDs.
Changed CSMTPMail::ProcessMessage() to accept VARIANTs of type VT_EMPTY in
place of missing optional parameters to achieve the same effect as
leaving them out.
Added complete documentation of LAFcommon.SMTPMail in the file
doc_SMTPMail.txt.
VERSION 2.5.2.0 -- 1/2/2001
Moved the class declarations and definitions of CAVLTreeNode, CCacheNode,
CObjectPoolNode and CQueueNode from their reusables_*Node.* files into
their respective reusables_*.* files. For example,
reusables_AVLTreeNode.h and reusables_AVLTreeNode.cpp have been merged
into reusables_AVLTree.h and reusables_AVLTreeNode.h. This should make
including these classes in other projects a simpler exercise.
Changed the behavior of the "select" element type in form_validations.js --
the value of the selected option must not be zero-length if the element
is required.
Removed the horribly out-of-date changelog entries from form_validations.js
and replaced them with usage instructions.
VERSION 2.5.1.0 -- 12/6/2000
Fixed CMisc::SpawnProcessAsUser() to open the thread token with
TOKEN_DUPLICATE access so CreateProcessAsUser() will succeed when running
as a user other than SYSTEM.
Discovered that the user calling CMisc::SpawnProcessAsUser() must have
"Act as part of the operating system", "Increase quotas" and "Replace a
process level token" permissions in NT User Manager. When this method is
invoked from an ASP application running "in a separate memory space", it
runs as IWAM_machinename who, by default, has none of these permissions.
If an ASP application is running in-process, it runs as SYSTEM, which
implicitly has all permissions.
Modified CMisc::SpawnProcessAsUser() to return the value from GetLastError()
in the process_info parameter if LAFCOMMON_MISC_error_cannot_spawn,
LAFCOMMON_MISC_error_cannot_change_user_context or
LAFCOMMON_MISC_error_cannot_login are being returned. This should aid
debugging in the future.
VERSION 2.5.0.0 -- 12/4/2000
Added CSMTP::text_file_attachment, CSMTP::html_file_attachment,
CSMTP::gif_file_attachment, CSMTP::jpeg_file_attachment and
CSMTP::binary_file_attachment as section types to read files from disk and
attach them to the message. If one of these section types are given, the
filename is expected as the content.
Fixed a bug in CSMTPQueue::canonicalize_message() that was occassionally
appending garbage characters to the end of the canonicalized text.
Renamed some of the preprocessor identifiers in reusables_SMTP.h so they
wouldn't conflict with existing code when the file is included in another
project.
VERSION 2.4.0.0 -- 11/21/2000
Added CMisc::SpawnProcessAsUser() to allow callers to start external
processes as a specific user. Because this is a potential avenue for
brute-force password attacks, all calls through this function are
serialized and given an unconditional 10 second delay (similar to
CPAM::authenticateUser(). NOTE: This function will always fail with
return code LAFCOMMON_MISC_error_cannot_login if the user does not have
"Log on as a batch job" permission on the server.
VERSION 2.3.1.0 -- 11/10/2000
Changed CSMTP::CSMTPQueue::canonicalize_message() so that it would not wrap
plain text message lines at 72 characters -- the correct length is 996.
VERSION 2.3.0.0 -- 11/9/2000
Added generate_nonsequential_id() to reusables_guid.* that generates
between 3 and 3000 GUIDs, selects two of them at random and XORs the first
eight characters of one with the last eight characters of the other. The
MD5 hash of the result is then calculated and returned. Additionally, the
hash is encoded in base 32 using an alphabet of
"ABCDEFGHIJKMNPQRSTUVWXYZ23456789" and preceded by "ID-", which reduces
the string length to 29 characters. NOTE: This function is intended to be
used to generate nonsequential identifiers so that the next/previous
elements in the series cannot be predicted. However, by XORing the two
GUIDs, the property of being globally unique is destroyed. The
identifiers returned by this function _should_ be unique within a single
running instance of a given program on a given machine. A second instance
of the same program, even on the same machine, may generate duplicate
identifiers. NOTE: Because of the extra operations, this function is at
least 100 times slower than generate_guid().
Added the COM function NonSequentialIDGen() to the interface LAFcommon.Misc
that returns a result from generate_nonsequential_id().
Added generate_short_guid() to reusables_guid.* that generates a GUID and
encodes it in base 32 using an alphabet of
"ABCDEFGHIJKMNPQRSTUVWXYZ23456789", reducing the string length to 26
characters.
Added the COM function ShortGuidGen() to the interface LAFcommon.Misc that
returns the result from generate_short_guid().
VERSION 2.2.3.0 -- 11/7/2000
Rewrote a good portion of CSMTP::CSMTPQueue::canonicalize_message so it would stop
eating text and begin actually working.
VERSION 2.2.2.0 -- 11/6/2000
Removed a pair of unneccessary LAFcommon-specific #include directives from
reusables_SMTP.h and reusables_SMTP.cpp that prevented those files from being
included in other projects.
Corrected a bug in CSMTP::capture_queue() that made reference to CCache::success
to use CAVLTree::success instead. This was only a semantic bug since the two
values are equal.
Fixed a bug in CSMTP::CSMTPQueue::canonicalize_message() that was causing a
buffer overrun in plain text messages.
Added a call to WSAStartup() to CSMTP::CSMTP() and a call to WSACleanup() to
CSMTP::~CSMTP() to facilitate brain-dead run time environments like Windows
Scripting Host that won't initialize the windows sockets subsystem on their own.
VERSION 2.2.1.0 - 10/26/2000
Fixed CSMTPMail::CSMTPMail() to set throw_errors to VARIANT_FALSE.
Added a default condition to the switch in CSMTPMail::return_code_to_hresult().
Changed LAFcommon.SMTPMail's interface so that AddSection(), QueueFlush, QueuePause(),
ProcessMessage() and WaitUntilEmpty() now return return codes instead of
communicating exclusively through ErrorMessage.
Removed the "Win32 Release MinDependency" configuration from the list of available
build configurations.
VERSION 2.2.0.0 - 10/25/2000
Created CSMTP as a complete replacement for CSendmail (and LAFcommon.SMTPMail as a
complete replacement for LAFcommon.Sendmail). It supports named queueing
similar to what CCOMCollection provides through its "SharedIndex" property,
full MIME 1.0 encoding support and a much cleaner API. Additionally, it
is much more polite to the mail server (sends termination signals and waits for
acknowlegment before dropping the connection) and has been written as a reusable
file to allow its inclusion in other projects without forcing those projects to
call LAFcommon through COM. As a result of this, use of CSendmail is now
deprecated.
Removed CMailMessage and CMailQueue and their files MailMessage.* and MailQueue.*.
Removed global_mailqueue() from globals.*.
Removed all logic from CSendmail and hooked it in as an interface to CSMTP.
Fixed a serious bug in replace_text() that would cause a buffer overrun if the
shortest target was longer than the longest replacement.
Added GetErrorFromVariant() to reusables_atlcom.* to make optional parameters
possible in COM interfaces -- optional parameters that are not supplied are visible
as VARIANTs of type VT_ERROR.
Fixed a potential problem in continually_expire_shared_collections() where the
start time was declared as a static variable. If the worker thread were ever
stopped, it would never be able to restart because the start time would not update.
Added CQueue::count() to return the number of nodes currently in the queue.
Added direct access member functions to CQueue that deal with CQueueNode* arguments
and return CQueueNode* data instead of void* data to make deriving classes from
CQueue and CQueueNode more useful. All of the direct access functions are named
after their standard equivalents but are preceeded by "internal_".
Fixed a pair of bugs in CQueue::remove_current_move_prev() and
CQueue::remove_current_move_next() that were returning the wrong local variable as
a void*, bypassing the compiler's type checking.
Modified CMisc::GuidGen() to use generate_guid() in reusables_guid.*.
Added the files reusables_guid.h and reusables_guid.cpp to house the GUID generation
functions instead of CMisc. Now projects can include those files directly instead
of being forced to call LAFcommon via COM. This deserved its own file instead of
being added to reusables_c.* because the RPC functions require linking against
rpcrt4.lib, which may not be desirable if the project isn't going to use GUIDs.
Fixed a potentially lethal bug in CObjectPool::~CObjectPool() that assumed
CObjectPool::delete_function was valid while destroying the contents of the pool.
Added GetBSTRFromString() to allow the creation of BSTRs from char* data without the
use of CStrings.
Removed CPAMprivate and moved all of its functionality into CPAM. The original need for
CPAMprivate was to accomplish the serialization of authentication requests, which can
be done more efficiently within CPAM.
Changed CPAM to use EnumPAMReturnCodes to make its return codes available through the
typelib. Because VBScript can't read typelibs, matching constants are also in
LAFcommon_vbs.txt.
Fixed a potential problem in CObjectPool::~CObjectPool() that would assert if
CObjectPool::delete_function was NULL.
VERSION 2.1.0.0 - 10/3/2000
Changed CSendmail::internal_sendmessage() to return LAFCOMMON_return_delivery_failure
if the remote server could be contacted but the message was refused some other reason.
Moved all of the version information into version.h, then included that file from
resource.h and LAFcommon.idl to make updating version numbers easier.
Moved the enumerated values CSendmail::delivery_modes, CSendmail::return_codes into
LAFcommon.idl as EnumDeliveryModes and EnumReturnCodes, respectively, and updated all
references in the code to reflect this.
Added the constants from EnumDeliveryModes and EnumReturnCodes to lafcommon_vbs.txt for
use in ASP. Hopefully this will reduce (and eliminate) the use of COM properties to
provide constant values.
Added VersionInfo() to CCOMCollection, CHTMLUtil, CJavascriptUtil, CMisc, CPAM, CSendmail
and CSQLUtil to provide a way to discover the version information of the installed
library without resorting to Win32 calls or physically going to the server and pulling
up the properties of the DLL.
VERSION 2.0.4.0 - 9/26/2000
Fixed a stupid programmer error in CMisc::Sleep that was causing the function to call
itself instead of the global Sleep() function. This _should_ have been causing stack
overflow errors...
VERSION 2.0.3.0 - 9/22/2000
Fixed a memory leak in CSendmail::internal_sendmail().
VERSION 2.0.2.0 - 9/20/2000
Added CMisc::Sleep() to provide a way for VBScript programs to pause for a specified
interval. This is especially useful when looping on CSendmail's asynchronous
queue to allow it to empty before exiting.
VERSION 2.0.1.0 - 8/15/2000
Changed GetStringFromVariant() and GetStringFromBSTR() to use WideCharToMultiByte()
instead of W2A() to avoid copying the string twice. Since W2A() calls
WideCharToMultiByte() after declaring stack space and measuring string length and
most of the LAF C++ COM components use GetStringFromVariant() at least once per method,
this should be a big performance win.
Overloaded GetStringFromVariant() and GetStringFromBSTR() to accept char**s in addition to
CString*s. These functions will allow string extraction directly to char*s without the
overhead of the CString class.
Changed CCOMCollection::put_Item() so that assigning a VARIANT marked VT_EMPTY in a
collection item will delete that item.
Added CAVLTree::traverse_preorder() and CAVLTree::traverse_postorder() mostly for
completeness' sake but also to aid in diagnostic testing of the AVL tree implementation
-- printing out two different traversals of the tree is easier to deal with than walking
the entire structure through the QuickWatch window in DevStudio.
Added the COM enumeration EnumTraversalOrders to be used as the source of the values
stored in LAFcommon.COMCollection.TraversalOrder. As it turns out, VBScript is too
brain-damaged to use COM enumerations, even though VB understands them. FTSOBG.
Added lafcommon_vbs.txt to provide the constant values contained in EnumTraversalOrders
so that VBScript can access them.
Added the COM property LAFcommon.COMCollection.TraverseOrder to allow the caller to set
the desired traversal order prior to getting the enumeration of the stored data. This
property's value defaults to inorder traversals.
Fixed a heap-corrupting bug in CCOMCollectionSharedNode::case_insensitive_find_function --
CString::Compare was being called instead of CString::CompareNoCase. Because
CCOMCollectionSharedNode::case_insensitive_find_function was actually comparing in a
case-sensitive manner while CCOMCollectionSharedNode::case_insensitive_comparison_function
was not, the cache of shared collections was becoming corrupt when the collections
expired and were removed. This was the cause of the observed assertions, crashes and
hangs in LAFcommon.CCOMCollection.
Changed CAVLTree::~CAVLTree() to delete all of the tree nodes when the tree is destroyed.
This _shouldn't_ cause any problems unless something is using the tree nodes in another
data structure. In any case, it plugs a potential memory leak.
VERSION 2.0.0.0 - 8/9/2000
Finally discovered how to accept function pointers through a COM interface, run the
referenced function and grab the output. As it turns out, VariantChangeType() does it
all. GetStringFromBSTR(), GetEmptyFromVariant(), GetBSTRFromVariant(),
GetStringFromVariant(), GetNumberFromVariant() and GetBooleanFromVariant() will all now
run VariantChangeType() to convert the given VARIANT to the expected type if it wasn't
of that type already. GetNumberTypeFromVariant(), GetArrayFromVariant() and
GetArrayTypeFromVariant() will also use VariantChangeType() if an additional parameter
is passed to indicate what type is desired. Because VariantChangeType() cannot convert
arrays from one type to another, no assumptions can be made about the the desired type.
The biggest benefit of this change is that ASP can now contain statements such as
"Foo.Bar(Request.Form("baz"))" instead of "Foo.Bar(CStr(Request.Form("baz")))".
Fixed a bug that was corrupting memory and throwing exceptions in
CAVLTree::SLOW_EXPENSIVE_LINEAR_NONINDEXED_subfind() by performing recursive actions on
NULL subtrees.
Fixed CSendmail::internal_sendmail() to check for the value INVALID_SOCKET to see if the
call to socket() succeeded.
Added CQueue::delete_function to provide the ability to delete the data stored in the queue
when the queue is destroyed.
Added flash_email.asp to provide Flash movies the capability to send email.
VERSION 1.9.10.0 - 7/28/2000
Added "creditcard", "visa", "mastercard", "americanexpress", "discover", "dinersclub" and
"jcb" as valid form element types in form_validations.js to facilitate credit card
processing.
Added GetStringFromBSTR() to reusables_atlcom.cpp as a way to convert BSTRs to CStrings.
Finally changed CAVLTree::SLOW_EXPENSIVE_LINEAR_NONINDEXED_find() and
CCache::SLOW_EXPENSIVE_LINEAR_NONINDEXED_hit() to return all of the matches, not just the
first one found.
VERSION 1.9.9.0 - 7/24/2000
Added GetEmptyFromVariant() as an analog to the Get*FromVariant() family of functions to
verify that a variant actually contains VT_EMPTY instead of inferring it when no other
datatype can be extracted from it.
Added CAutoArray::init() as an explicit initializer to allow CAutoArray objects to be
constructed using _alloca().
Added CAutoArray::empty() and CAutoArray::delete_function to allow the destructor to delete
the objects stored in the array.
VERSION 1.9.8.0 - 7/18/2000
Fixed GetStringFromVariant() to use W2CA() instead of wcstombs(). Apparently wcstombs()
cannot deal with Unicode characters that cannot be mapped to a value on the ANSI character
map and stops. W2CA() converts the unmappable Unicode character into two bytes anyway and
continues, which is what is needed. FTSOBG.
Fixed a potentially fatal bug in CStack::empty() that would attempt to free the stack's array
even if there were no elements in the array.
Converted CAutoArray, CHeap and CStack to use realloc() to extend their arrays instead of
unconditionally reallocating the memory and freeing the old array. This should provide a
performance win as well as helping to prevent heap fragmentation on long-running processes.
VERSION 1.9.7.0 - 7/17/2000
Added find_function and compare_void_ptrs() to CHeap.
Fixed a major data corruption issue in CHeap and (by extension) CCache. When CHeap::remove()
was called, it was using comparison_function to perform a linear search of the heap array
for the target element. This technique is low cost because the most common caller of
remove() is pop(), whose target element is always the first element in the array. However,
the target element was never being found with comparison_function if the node's comparison
data had changed since the target node was initially located, as is the case with
CCache::remove(). By providing a separate find_function, this situation can be avoided by
providing a separate function to compare the objects in the case of removal. By default,
this function is set to CHeap::compare_void_ptrs(). This bug was introduced in version
1.9.3.0 and was located by Ryan Carver.
Fixed CCache::remove() to pass the correct pointer address to CHeap::remove() instead of the
address of the correct address (found_node was not being dereferenced). This bug was
introduced in version 1.9.3.0 and was located by Ryan Carver.
VERSION 1.9.6.0 - 7/15/2000
Fixed CPAMprivate::authenticateUser() to unlock the mutex if the database connection calls
throw exceptions.
Fixed html_canonicalize_no_break() in reusables_mfc.cpp so that it wouldn't walk off the end of
the targets and replacements arrays.
Changed all functions that accepted CStrings as arguments to accept CString*s instead, to avoid
the overhead of making a copy of the string for the local variable.
Added overloaded versions of html_canonicalize(), html_canonicalize_no_break(),
sql_canonicalize() and javascript_canonicalize() that accept CString*s as parameters.
Changed CPAMprivate::authenticateUser() to open its recordset without creating a temporary
stored procedure on the server.
VERSION 1.9.5.0 - 7/14/2000
Fixed html_canonicalize() in reusables_mfc.cpp to not replace "<" with "<" and immediately
replace "&" with "&".
Changed CHTMLUtil::canonicalize() and CHTMLUtil::canonicalize_no_break() to call
html_canonicalize() and html_canonicalize_no_break() (respectively) in reusables_mfc.cpp
instead of reusables_c.cpp.
Fixed CMisc::QuickSort() to return a SAFEARRAY of the same shape as the one it originally
received instead of unconditionally setting the lower bound to 1.
VERSION 1.9.4.0 - 7/10/2000
Added CMisc::QuickSort() to provide a general-purpose sorting algorithm for ASP to use on arrays
of strings.
Changed the first parameter of quicksort() from void*[] to void** to make it work with other
array types casted to void**.
Fixed quicksort() so it would sort instead of shuffle.
Changed GetStringFromVariant() to use wcstombs() instead of passing through a _bstr_t object to
extract the BSTR as a char*. This should be a major performance win.
Added GetBSTRFromVariant() to extract the BSTR from a VARIANT without converting it to a char*.
VERSION 1.9.3.0 - 7/8/2000
Fixed a bug in GetNumberTypeVariant that was leaving the return value completely uninitialized
in all cases, meaning that the function almost always returned a non-zero integer.
Added CQueue::empty() to provide a way to empty the queue without having to destroy the object.
Changed CStack to use an array of void*s instead of a separate object for every datum. This
should help performance somewhat. As a result, the class CStackNode was removed and the
files reusables_StackNode.cpp and reusables_StackNode.h were deleted.
Changed CHeap to use an array of void*s instead of a separate object for every datum. This
should help performance somewhat, except in cases where an element in the middle of the heap
is to be updated, such as when a cache element's timestamp is changed. For large caches, this
may become expensive enough that keeping track of the heap indecies elsewhere (such as in
CCacheNode) may become worthwhile. As a result, the class CHeapNode was removed and the
files reusables_HeapNode.cpp and reusables_HeapNode.h were deleted.
Fixed CCOMCollection to make copies of its data using VariantCopyInd() instead of VariantCopy().
ASP passes in most of its data in VARIANTs marked VT_BYREF, which (apparently) VariantCopy()
does not copy correctly.
VERSION 1.9.2.0 - 7/6/2000
Removed some cruft from CCOMCollectionNode::CCOMCollectionNode().
Added GetArrayTypeFromVariant() as a counterpart to GetArrayFromVariant() to determine the
type of information stored in the array.
Changed CHeap::~CHeap() to destroy all of the nodes as well as the heap array.
Added CQueue and CQueueNode as a general-purpose FIFO queue with enhancements to allow accesses
in the middle of the queue.
Added the property COMCollection.EnumerateKeys to allow the caller to specify if the stored
keys should be enumerated instead of the data associated with each key since _NewEnum
can't be easily made to accept an additional parameter.
Cleaned up a large amount of ASP-related cruft in CCOMCollection, CHTMLUtil, CJavascriptUtil,
CMisc, CPAM, CSendmail and CSQLUtil. Specifically, the onStartPage and onEndPage functions
were removed, along with all of the pointers to the ASP objects.
VERSION 1.9.1.0 - 7/1/2000
Fixed CCOMCollection::put_CaseSensitive() and CCOMCollection::get_CaseSensitive() to use the
current (shared) collection instead of always using the internal (non-shared) collection.
Removed CCOMCollection::EmptyAll() because it was simply too dangerous -- the potential for
misuse was way too high.
VERSION 1.9.0.0 - 6/30/2000
Fixed a problem with new CMisc::ByteArray2String() to return the entire byte array rather
than the first nibble of each byte.
Removed the references to resource.h and stdafx.h in reusables_AutoArray.cpp,
reusables_AVLTree.cpp, reusables_AVLTreeNode.cpp, reusables_Cache.cpp,
reusables_CacheNode.cpp, reusables_Heap.cpp, reusables_HeapNode.cpp,
reusables_ObjectPool.cpp, reusables_ObjectPoolNode.cpp, reusables_Stack.cpp and
reusables_StackNode.cpp to make it possible to use those files in non-MFC projects.
Corrected a bug in CAVLTree::absorb() that was causing the absorbing tree to always completely
rebuild the absorbed tree even if the absorbing tree was already empty. Along the way, the
absorbing tree was resetting its internal element counter to zero, causing
CAVLTree::traverse_inorder() to malfunction.
Added CAVLTree::get_num_elements() to provide access to the number of elements in the tree,
since the class keeps track of that information anyway.
Added GetNumberTypeFromVariant() as a counterpart to GetNumberFromVariant() to determine what
type of number is contained by the variant, since GetNumberFromVariant() converts the number
regardless of its original type.
Overloaded CAVLTree::traverse_inorder() to allow each element, as it is located, to generate
a callback to a function pointer instead of unconditionally allocating (huge amounts of)
memory on the heap to duplicate the tree's contents.
Overloaded CCache::hit(), CCache::add() and CCache::remove() to deal with CCacheNode pointers
directly instead of void pointers. This allows the ability to subclass CCacheNode and not
have CCache automatically wrap it in another CCacheNode.
Changed CCache::expire_entries() and CCache::remove() to allow the delete_function to be NULL.
Added LAFcommon.COMCollection as a substitute for the general-purpose collection engine
provided by ASP's session variables. LAFcommon.COMCollection also provides the ability to
share a collection across thread boundaries by setting the COMCollection.SharedIndex
property to a non-Empty value.
VERSION 1.8.0.0 - 6/21/2000
Fixed CObjectPool::get_object() not to cause a memory violation if all of the objects in the
pool were expired for any reason.
Fixed a memory leak in CStack::empty() that would manifest if CStack::delete_function was
non-NULL.
Added CMisc::ByteArray2String() to convert a VARIANT-encapsulated SAFEARRAY of BYTE data to
a string representation of the BYTE hex values. This is specifically for use by the
ticketing system to convert ADSI user SIDs to strings.
VERSION 1.7.6.0 - 6/13/2000
Fixed a small thinko in CAVLTree::remove() that was corrupting the tree by not recalculating
the nodes' heights properly after a removal.
VERSION 1.7.5.0 - 6/9/2000
Fixed a logic error in CAVLTree::remove() that was corrupting the tree by losing track of
the target node's replacement whenever the target node had a height of 1.
Fixed a nasty bug in CAVLTree::remove(). CAVLTree::rebalance() was being passed a pointer to
a local variable instead of a pointer to the pointer within the tree that stored the node's
location. Thus, any changes below the node were saved but changes to the node's position
in the tree were not. Result: Massive data corruption.
VERSION 1.7.4.0 - 5/11/2000
Fixed CAutoArray::sort() so it would sort arrays with only two elements.
Fixed quicksort() so it would actually sort by correcting its understanding of what the
comparison function returns.
VERSION 1.7.3.0 - 5/9/2000
Changed the date format in CSendmail::internal_sendmessage() to accomodate Netscape
Communicator. Apparently, Communicator is NOT RFC-822 compliant -- it does not accept
timezone names, only numeric representations of the difference between GMT and local time.
VERSION 1.7.2.0 - 4/11/2000
Fixed validate_isInteger() in form_validations.js so that integers could not contain negative
exponentiations.
Added CHeap::is_initialized() to provide a way for external methods to tell if the heap is
ready to be used.
Added CObjectPool and CObjectPoolNode to provide a reusable object pool system. Though it is
intended primarily for database connection pooling, it makes no assumptions about the objects
it is holding -- allowing it to be used with any type of object. It allows a maximum pool
size and a maximum object age to be specified.
Fixed validate_isInteger() in form_validations.js so that the exponential delimiter ("e" or "E")
can only be specified once.
Fixed several in form_validations.js where the String.replace() function was being called but
the conditional would always conclude the format was correct.
VERSION 1.7.1.0 - 3/15/2000
Fixed a serious bug in CCache::empty() that was calling CAVLTree::remove with parameters of
the wrong type. It now calls (*get_indexed_field)() to obtain the correct pointer to pass.
This bug was throwing an exception every time the function was called.
Changed the growth pattern of CHeap -- it now will grow by increment_size elements until the
size of the heap is equal to or greater than increment_size * 10. After that, it will
double in size every time it reallocates. This should significantly improve performance in
situations where the heap is growing rapidly towards a large upper bound.
Added CHTMLUtil::canonicalize_no_break() and ::html_canonicalize_no_break() to both
reusables_c.* and reusables_mfc.* to canonicalize an HTML string without replacing the
linebreaks with "
" tags. This is primarily for use in HTML TEXTAREAs.
VERSION 1.7.0.0 - 3/13/2000
Added an asynchronous mail delivery system to CSendmail::Sendmessage(). It fires off a
preset number of worker threads to deliver mail in the background. Added several properties
to LAFcommon.Sendmail to facilitate this: Delivery_Mode (get, put), Max_Worker_Threads (get,
put), Queue_Size (get), LAFSendmail_Deliver_Synchronous (get) and
LAFSendmail_Deliver_Asynchronous (get). If the background mail delivery fails, the
message(s) are quietly discarded. This should be changed to produce log messages at
minimum. Also, there is currently no way to clear the queue of messages or show the
contents of the queue.
Moved sendmail_return_codes inside the CSendmail class where it belongs.
Added the value SRCbad_parameter to sendmail_return_codes for use by CSendmail::SendMessage
and added the property LAFcommon.Sendmail.LAFSendmail_Bad_Parameter for use by external
clients.
Changed CSendmail::is_initialized() to return false if the SMTP port or the sender's email
address haven't been specified, in addition to checking the SMTP server name.
VERSION 1.6.5.0 - 2/28/2000
Added quicksort() to reusables_c.cpp as a generic quicksort routine. This implementation is
recursive and requires the caller to provide a pointer to a comparison function.
Added CAutoArray::sort() to sort the array using quicksort().
Added a parameter to CAVTree::traverse_inorder() to allow the caller to provide a pointer to
a function to clone the elements as they are traversed. This is to allow for the situation
where a traversal is to be stored separately after the tree is destroyed.
Fixed a potentially nasty bug in CAVLTree::empty() that could have potentially resulted in
attempting to free the NULL pointer.
Added CAVLTree::absorb() to merge the contents of two AVL trees into one tree. It is the
caller's responsibility to ensure that the merge makes sense (both trees storing the same
datatype; the find_function, delete_function and comparison_function working for the contents
of both trees).
VERSION 1.6.4.0 - 2/3/2000
Fixed CSendmail::Sendmessage to send a carriage return as well as a linefeed at the end of each
of its lines so that mail servers that are strictly compliant with RFC 822 will work.
VERSION 1.6.3.0 - 1/24/2000
Added support to email.asp to replace the sequence ###\n### with a line break.
Fixed CSendmail::SendMessage to be RFC822-compliant: it now sends the correct header fields in
the correct order, in addition to formatting the date properly. The resultant messages are
now visible in Netscape for Mac, which is apparently rather picky about such things.
Added the property LAFcommon.Sendmail.reply_to, which holds the Reply-to addresses for the
new messages. If no value is given, the value of LAFcommon.Sendmail.sender_email is used.
VERSION 1.6.2.0 - 1/15/2000
Fixed a pair of subtle bugs in CAVLTree::rotate_double() and CAVLTree::rebalance that were
corrupting the tree.
VERSION 1.6.1.0 - 12/20/1999
Added CCache::get_timeout() and CCache::set_timeout() to allow cache timeouts to be configured
after the cache has been initialized.
Removed the configurations "Win32 Unicode Debug", "Win32 Unicode Release MinSize" and "Win32
Unicode Release MinDependency" from the build configuration options.
VERSION 1.6.0.0 - 12/17/1999
Added reusables_mfc.h and reusables_mfc.c to hold new implementations of sql_canonicalize(),
html_canonicalize() and javascript_canonicalize(). These new versions work on CStrings
instead of char *s.
VERSION 1.5.3.0 - 12/15/1999
Added CStack::empty() and CStack::delete_function to facilitate the use of CStack outside of
CAVLTree. CStack::delete_function is a callback to a function that knows how to delete the
objects CStack is storing. CStack::delete_function is NULL by default; it is not called if
NULL. CStack::empty() forcibly empties the stack of all its elements, passing them to
CStack::delete_function if it is set.
VERSION 1.5.2.0 - 12/14/1999
Corrected a bug in CCache that corrupted the AVL tree when removing items. It required the
addition of a get_indexed_data function pointer to get the actual field that the AVL tree
indexes. This procedure probably needs to be reexamined.
VERSION 1.5.1.0 - 12/12/1999
Extended CAVLTree to allow a runtime-defined delete function. This is needed so
CAVLTree::empty() can delete the data being stored by the tree as well as deallocating the
tree structure itself. This is not needed when using CAVLTree though CCache, but it becomes
handy if CAVLTree is being used alone.
Audited CHeap and found an embarrassing number of bugs:
Fixed a bug in CHeap::remove() wherein the element being moved from the bottom of the heap
to the top would not have its heap_index member updated if CHeap::heap_down() did not take
action. This meant that, for all practical purposes, the heap was being corrupted.
Corrected a major bug in CHeap that would (should) have eventually crashed the program
running code -- CHeap::add()'s reallocation of the available heap space only worked the
first time it was called; any subsequent expansions only wrote off into unallocated memory.
Corrected a major bug in CHeap::pop() to remove the assumption that the heap was not empty.
Violating that assumption would have meant pseudo-random memory corruption within the heap
or a crash, depending on the value found at CHeap::heap[0]->heap_index.
Corrected CHeap::heap_down() to make the correct comparisons between nodes in the heap. It
was contradicting itself in its comparison behavior (in one place behaving like a
maximizing heap and in another behaving like a minimizing heap).
VERSION 1.5.0.0 - 12/11/1999
Deprecated the implementations of "CString GetStringFromVariant(VARIANT *)" and
"SAFEARRAY *GetArrayFromVariant(VARIANT *)" in favor of the new functions
"int GetStringFromVariant(VARIANT *, CString *)" and
"int GetSafeArrayFromVariant(VARIANT *, SAFEARRAY **)", respectively. Both of the new
functions take a new parameter -- the location into which they are to store the result. If
the data cannot be extracted from the VARIANT, the second parameter is not touched and 0 is
returned. If the data can be extracted, the second parameter is changed to contain its
value and 1 is returned. The deprecated versions of the functions still exist for backward
compatibility, though they now call the new versions and interpret the results.
VERSION 1.4.0.0 - 12/9/1999
Moved the guts of HTMLUtil.canonicalize, JavascriptUtil.canonicalize and SQLUtil.canonicalize
into html_canonicalize(), javascript_canonicalize() and sql_canonicalize(), respectively.
These three new functions are located in reusables_c.c. This was done so that other C++
projects could use these functions directly instead of having to invoke the overhead of
passing strings through COM. Hopefully this will make string canonicalization less painful
along fast paths. NO CHANGES MADE TO EXTERNAL INTERFACE.
VERSION 1.3.4.0 - 12/3/1999
Changed GetBooleanFromVariant to return a failure flag instead of FALSE if a boolean could not
be extracted from the VARIANT. The boolean is now returned in a pass-by-reference parameter.
VERSION 1.3.3.0 - 12/1/1999
Added AVLTree.SLOW_EXPENSIVE_LINEAR_NONINDEXED_find() to find an element in the AVLTree given
an arbitrary search function. This function is so named because it actually does a preorder
traversal of the tree and stops when it finds a match. The worst-case complexity of this
search is O(n) if the target element is the largest one in the tree.
*** NOTE *** NOTE *** NOTE *** This function searches the tree in preorder and stops when it
finds a single match. Because the search uses an arbitrary search function to search against
arbitrary criteria, there may be multiple matches within the tree if only this function were
to continue searching. Only the first match is returned.
Added CCache.SLOW_EXPENSIVE_LINEAR_NONINDEXED_hit() to find an element in the cache given
an arbitrary search function. This function uses
AVLTree.SLOW_EXPENSIVE_LINEAR_NONINDEXED_find() to locate the element. There is no
performance penalty for the heap once the element has been located.
*** NOTE *** NOTE *** NOTE *** This function locks the cache as a read-only thread while it
works; all updates to the cache will BLOCK while this function executes. USE THIS FUNCTION
SPARINGLY OR NOT AT ALL!
VERSION 1.3.2.0 - 11/11/1999
Changed Misc.GuidGen() to produce GUIDs of length 32 instead of 36. This is done by cutting
out the hyphens in the GUIDs.
VERSION 1.3.1.0 - 11/5/1999
Added translation of carriage returns and linefeeds to line breaks in HTMLUtil.canonicalize().
Added GetDateTimeFromVariant() to reusables_atlcom.cpp since a Variant marked VT_EMPTY will
generate a COleDateTime with a status COleDateTime::valid, even though the object's actual
data is invalid.
VERSION 1.3.0.0 - 11/3/1999
Added JavascriptUtil to canonicalize strings for use in Javascript code.
VERSION 1.2.2.0 - 10/20/1999
Reworked CCacheNode not to inherit from CAVLTreeNode and CHeapNode, since it appears that the
MSVC++ compiler doesn't handle multiple inheritance correctly when there is complex pointer
casting going on around stack boundaries.
Added get_max_index() to CAutoArray, which returns the greatest index accessed so far.
VERSION 1.2.1.0 - 10/19/1999
Moved the enumerated result types from outside the CAVLTree, CCache and CHeap classes inside
them.
Added GetBooleanFromVariant() to reusables_atlcom.cpp.
Fixed small bug in GetArrayFromVariant().
VERSION 1.2.0.0 - 10/13/1999
Created CSendmail
CSendmail.IsInitialized() will return a boolean value indicating if the initialization of
MAPI was successful.
CSendmail.Sendmail() will send a given message with a given subject to a given recipient.
VERSION 1.1.5.0 - 10/1/1999
Added CCache.empty() to dump cache contents before the object is destroyed.
VERSION 1.1.4.0 - 9/30/1999
Plugged a memory leak in both HTMLUtil.canonicalize() and in SQLUtil.canonicalize().
VERSION 1.1.3.0 - 9/29/1999
Changed the locking inside CCache to handle read-only threads versus threads that need
exclusive access to the structures.
VERSION 1.1.2.0 - 9/28/1999
Added CAVLTree, CAVLTreeNode, CCache, CHeap, and CHeapNode.
VERSION 1.1.1.0 - 9/24/1999
Took out the replacements of linebreaks and carriage returns with "
" in
HTMLUtil.canonicalize().
VERSION 1.1.0.0 - 9/23/1999
Added CCacheNode, CStackNode and CStack.
Began work on CAVLTree.
VERSION 1.0.2.2 - 9/22/1999
No behavioral changes -- split reusables.[h/cpp] into reusables_atlcom.[h/cpp] and
reusables_c.[h/cpp] because including the ATL COM stuff into non-ATL COM projects would
cause linker errors when attempting to find endthreadex() and friends.
Added translation of "\n\r" into "
" to HTMLUtil.canonicalize().
VERSION 1.0.2.1 - 9/22/1999
Changed the behavior of HTMLUtil.canonicalize() and SQLUtil.canonicalize() to perform as
expected -- they were both changing any unprintable characters to '?'s. Unfortunately,
carriage returns, newline and tabs were not printable according to isprint(). These
characters are now handled as special cases.
Added spider_directories() to reusables.cpp, since I seem to be using it quite a bit.
VERSION 1.0.2.0 - 9/20/1999
Changed the CPAM.authenticateUser() system to enforce a single instance of itself internally
rather than relying on the caller to do this. This was needed to use the CPAM system from
ASP pages.
Renamed globals.h and globals.cpp to reusables.h and reusables.cpp, respectively.
VERSION 1.0.1.1 - 9/15/1999
Corrected the MUTEX_LOCK_TIMEOUT to indicate time in milliseconds, not in seconds.
VERSION 1.0.1.0 - 9/10/1999
Created CMisc
CMisc.GuidGen() will create a 36 character representation of a GUID using the "Registry"
format without the leading and trailing curly braces.
Added more HTML translations to CHTMLUtil.canonicalize().
VERSION 1.0.0.1 - (INITIAL VERSION) 9/9/1999
Created CPAM
CPAM.AuthenticateUser() will take a database connection string and select statement. It
will open a database connection using the provided connection string and run the select
statement to create a recordset. If the recordset is empty, LAFPAM_FAIL is returned.
If the recordset is empty, LAFPAM_SUCCEED is returned. Additionally, if the database
connection string does not work, LAFPAM_DBERROR is returned.
The idea behind this method is to provide a centralized, thread-independent mechanism for
authenticating usernames and passwords. A process can hold a single instance of CPAM
and access it using multiple threads. CPAM will then serialize the access and introduce
an unconditional delay of one second before returning the result. The idea behind this
system is this: If an attacker is trying to brute-force guess an online username/password
system, he's going to hit the site many thousands of times simultaneously. Typically,
he's going to gauge success or failure on the response time, not on the actual return
value. By using CPAM, all authentication requests are forced to be served one at a time,
regardless of the number of concurrent requests. Additionally, due to the one second
delay, thousands of attempts will incur a serious time penalty that most attackers are
not willing to pay.
Created CHTMLUtil
CHTMLUtil.canonicalize() will take a string and replace all HTML-sensitive characters with
their HTML-safe equivalent character sequences. NOTE: This is not the same as URL-
encoding the same string. In URL-encoding, spaces are changed to pluses ('+') and any
other non-alphanumeric character is changed to a percent sign ('%') and its corresponding
ASCII value represented as a two-character hexadecimal number. Canonicalizing an HTML
string will replace characters such as greater than ('>') with an HTML-safe
representation (">").
Created CSQLUtil
CSQLUtil.canonicalize() will remove single quote characters ('\'') and replace them with
two single quote characters ("''") so the string can safely be used as a text field in
a SQL statement.