A very strange bug. www.monkeyclaus.org is run by a cms I'm
developing. One of types of users we allow is "justTestingTheSite", a
type of user I developed to give demo's to prospective clients. The
purpose of this level of security is to let someone log in and see
everything as if they were root, and yet not be able to update or
delete anything, as they have no real priveledges at all.
I just logged in as root and created such an account, then I log out
and logged back in using the new account. I tried to edit the weblog
on the front page of the site. Everything worked as it should of: I
was able to get to the screen, edit it, and hit submit, and then,
because of my low security rating, the software did not change the
values. Perfect.
But the results message said "You've just updated 26 items." I was
expecting it to say "You've just updated 0 items." 26 just happens to
be the number of entries on the weblog which is the front page of the
site. For the life of me, I can not figure out how the software got
the number 26. More so, the message seems to be incorrect, none of the
26 items seems to have been updated.
A function and a class method are involved, if anyone can see where
the software is getting the number of weblog entries, I'll be most
pleased.
function standardUpdate($functionForEditing) {
global $users;
$users->check();
extract($config=getConfig());
global $cbKeyword01, $cbKeyword02, $cbKeyword03, $cbKeyword04,
$cbKeyword05, $cbKeyword06, $cbKeyword07, $cbKeyword08, $cbKeyword09,
$cbKeyword10;
global $cbId;
global $cbHeadline,$cbMainContent,$cbDateCreated,$cbWhich Type,$cbUserName,$cbPassword,$cbIsLoggedIn,$cbDate sModified,$cbLastModified,$cbDatesWhenViewed,
$cbLinksToWhatUrl,$cbOOA,$cbSection;
global $cbKeywords,$cbBelongsToWhichWebsite,$cbBelongsToW hichPage,$cbUserSecurityLevel,$cbNavTextDifFromHea dline,$cbNavText,$cbNavOOA,$cbNavSection,$cbTempla te,$cbSpecialOverrideCSSClass;
global $cbExpirationDate,$cbModifier01,$cbModifier02,$cbM odifier03,$cbModifier04,$cbModifier05,$cbModifier0 6,$cbModifier07,$cbModifier08,$cbModifier09,$cbMod ifier10,$cbModifier11,$cbModifier12;
global $cbModifier13,$cbModifier14,$cbModifier15,$cbModif ier16,$cbModifier17,$cbModifier18,$cbPublicName,$c bEmail,$cbUrl,$cbWhenLoggedIn,$cbBelongsToWho,$cbN umTimesViewed,$cbNumTimesViewedLast24;
global $cbNumTimesViewedLastWeek,$cbNumTimesViewedLastMon th,$cbIsFrontPage,$cbPagePassword,$cbUserAddress,$ cbModifier19,$cbModifier20,$cbModifier21,$cbModifi er22,$cbModifier23,$cbModifier24,$cbStyle;
global $cbAllowComments,$cbListOfAllFilesThatBelongToThis Entry,$cbIsRoughDraft,$cbHowManyEntriesShouldWeLis tOnThisPage,$cbUndo;
global $forms, $io, $users, $links, $sql;
global $cbPassword1, $cbPassword2;
if ($cbKeyword01) $cbKeywords = $cbKeyword01.",\n";
if ($cbKeyword02) $cbKeywords .= $cbKeyword02.",\n";
if ($cbKeyword03) $cbKeywords .= $cbKeyword03.",\n";
if ($cbKeyword04) $cbKeywords .= $cbKeyword04.",\n";
if ($cbKeyword05) $cbKeywords .= $cbKeyword05.",\n";
if ($cbKeyword06) $cbKeywords .= $cbKeyword06.",\n";
if ($cbKeyword07) $cbKeywords .= $cbKeyword07.",\n";
if ($cbKeyword08) $cbKeywords .= $cbKeyword08.",\n";
if ($cbKeyword09) $cbKeywords .= $cbKeyword09.",\n";
if ($cbKeyword10) $cbKeywords .= $cbKeyword10.",\n";
$sql->setValue("cbHeadline", $cbHeadline);
$sql->setValue("cbMainContent", $cbMainContent);
$sql->setValue("cbWhichType", $cbWhichType);
$sql->setValue("cbPassword", $cbPassword1);
$sql->setValue("cbLinksToWhatUrl", $cbLinksToWhatUrl);
$sql->setValue("cbOOA", $cbOOA);
$sql->setValue("cbSection", $cbSection);
$sql->setValue("cbKeywords", $cbKeywords);
$sql->setValue("cbBelongsToWhichPage", $cbBelongsToWhichPage);
$sql->setValue("cbNavTextDifFromHeadline",
$cbNavTextDifFromHeadline);
$sql->setValue("cbNavText", $cbNavText);
$sql->setValue("cbNavSection", $cbNavSection);
$sql->setValue("cbNavOOA", $cbNavOOA);
$sql->setValue("cbStyle", $cbStyle);
$sql->setValue("cbTemplate", $cbTemplate);
$sql->setValue("cbSpecialOverrideCSSClass",
$cbSpecialOverrideCSSClass);
$sql->setValue("cbExpirationDate", $cbExpirationDate);
$sql->setValue("cbModifier01", $cbModifier01);
$sql->setValue("cbModifier02", $cbModifier02);
$sql->setValue("cbModifier03", $cbModifier03);
$sql->setValue("cbModifier04", $cbModifier04);
$sql->setValue("cbModifier05", $cbModifier05);
$sql->setValue("cbModifier06", $cbModifier06);
$sql->setValue("cbModifier07", $cbModifier07);
$sql->setValue("cbModifier08", $cbModifier08);
$sql->setValue("cbModifier09", $cbModifier09);
$sql->setValue("cbModifier10", $cbModifier10);
$sql->setValue("cbModifier11", $cbModifier11);
$sql->setValue("cbModifier12", $cbModifier12);
$sql->setValue("cbModifier13", $cbModifier13);
$sql->setValue("cbModifier14", $cbModifier14);
$sql->setValue("cbModifier15", $cbModifier15);
$sql->setValue("cbModifier16", $cbModifier16);
$sql->setValue("cbModifier17", $cbModifier17);
$sql->setValue("cbModifier18", $cbModifier18);
$sql->setValue("cbPublicName", $cbPublicName);
$sql->setValue("cbEmail", $cbEmail);
$sql->setValue("cbUrl", $cbUrl);
$sql->setValue("cbIsFrontPage", $cbIsFrontPage);
$sql->setValue("cbPagePassword", $cbPagePassword1);
$sql->setValue("cbUserAddress", $cbUserAddress);
$sql->setValue("cbModifier19", $cbModifier19);
$sql->setValue("cbModifier20", $cbModifier20);
$sql->setValue("cbModifier21", $cbModifier21);
$sql->setValue("cbModifier22", $cbModifier22);
$sql->setValue("cbModifier23", $cbModifier23);
$sql->setValue("cbModifier24", $cbModifier24);
$sql->setValue("cbAllowComments", $cbAllowComments);
$sql->setValue("cbListOfAllFilesThatBelongToThisEntry ",
$cbListOfAllFilesThatBelongToThisEntry);
$sql->setValue("cbIsRoughDraft", $cbIsRoughDraft);
$sql->setValue("cbHowManyEntriesShouldWeListOnThisPage" ,
$cbHowManyEntriesShouldWeListOnThisPage);
$sql->update($cbId);
$total = $sql->db->affected();
if ($cbPagePassword1 != $cbPagePassword2) {
$functionForEditing($cbId, "The two passwords that you typed did not
match one another.");
die();
}
if ($cbId) {
startPage("Your entry was updated in the database. $total enties
were affected.");
defaultScreen();
endPage();
} else {
startPage("There was some kind of problem. Your entry could not be
updated in the database.");
defaultScreen();
endPage();
}
}
function update($cbId, $checkIfUserIsSafe="y", $field1="",
$operator1="=", $value1="", $field2="", $operator2="=", $value2="",
$field3="", $operator3="=", $value3="") {
if (!$this->userIsSafe && $checkIfUserIsSafe=="y") {
return false;
} else {
// 06-19-03 - because of the if tests there is no way for this
function to blank an entry. In other words, if a user has entered
// a title for their webpage, but then later decides they don't
want any title at all, they can't blank it, because a empty field
// will fail the if test here. We must test for the presense of
"#x#blank#x#" - lk
$this->cbLastModified = time();
// 06-21-03 - we will need to give potential clients the ability to
come in and kick the tires,
// see everything, and yet we don't want them to be able to change
anything. Therefore, we set up
// this special test, looking to see if the user is marked as
"justTestingTheSite".
// We test for the presense of such a security rating and only
proceed if the check fails
// (if the user is not so marked). -lk
if (!stristr($this->userSecurityLevel, "justTestingTheSite")) {
// 07-05-03 - We want to be able to offer at least one level of
undo to the user. Therefore we need to first back up the previous
// version of this entry, in a string marked by a separator that
can later be used to bust it into an array and turn it back into an
// entry if they should choose to undo their work. A flag will
also need to be set, so that the function startPage will know to
// display the "undo" text option.
$entry = $this->getJustOneEntry($cbId);
// IMPORTANT !!! If more fields are added to the database, this
next line will have to be changed.
// 07-07-03 - this next line is to make sure that cbUndo isn't
included in the next undo
array_pop($entry);
$cbUndo = implode("\n\n\n##%%^***%%##", $entry);
$this->setValue("cbUndo", $cbUndo);
$this->setFlagForUndo($cbId);
// THE QUERY
// 07-05-03 - and now we finally start building the query string -
lk
$query = "UPDATE mcContentBlocks SET ";
// 07-07-03 - CAREFUL!!!! I just erased this next line, not
realizing what it was. This is not $sql->reset, but the built-in PHP
function, reset.
// It is reseting the pointer in the array. In future, having
methods with the same name as PHP functions may not be a good idea.
reset($this->tableValues);
while (list($key, $val) = each($this->tableValues)) {
// 06-20-03 - the following if restrictions means that a special
function will have to handle
// changing the value of cbUserName, or cbDateCreated.
if ($key != "cbBelongToWhichWebsite" && $key != "cbDateCreated"
&& $key != "cbUserName") {
// 06-24-03 - this next line is the line that makes sure blank
values get left out.
if ($val) {
// 06-20-03 - in this next bit we're going to test for
"#x#blank#x# which is what a user should type
// in if they really want a field to be blank. We're going to
use trim() and strtolower() to try to
// minimize the number of errors that might come happen because
of the user's inconsistent typing.
$blank = trim($this->$val);
$blank = strtolower($blank);
if ($blank == "#x#blank#x#") {
$query .= $key."='', ";
} else {
$query .= $key."='$val', ";
}
}
}
}
// 06-19-03 - because of the if clauses above we can't know which
of the above is the last, therefore we need the next line to take
// the comma off the end of the query, otherwise we get SQL
errors.
$query = substr($query, 0, -2);
$query .= " WHERE cbId=$cbId ";
// 07-05-03 - last week working on the user class I invented an
$sql method called updateWithConditions. Later I decided it was a big
// mistake having more than one update method. So now I've gotten
rid of the other method and added the functionality here. This method
// accepts up to 3 extra conditions to the WHERE clause.
if ($field1) $query .= " AND $field1 $operator1 '$value1' ";
if ($field2) $query .= " AND $field2 $operator2 '$value2' ";
if ($field3) $qeury .= " AND $field3 $operator3 '$value3' ";
$query .= " AND cbBelongsToWhichWebsite='$this->cbBelongsToWhichWebsite'";
$this->db->query($query);
echo $query;
$this->db->rows();
$this->reset();
return $this->db->numRows;
} //ends if(!$test) clause
}
$this->reset();
}