Twitter: raymondcamden

Address: Lafayette, LA, USA

Friday Puzzler - Getting even with Bob

03-30-2007 3,535 views ColdFusion 12 Comments

For today's Friday Puzzler (remember those?), I'm going to describe a hypothetical situation that will be - unfortunately - a bit too familiar for most readers. You are a worker at MegaCorp Web, a large web design firm in greater Podunk. One of the banes of your existence is Bob. Bob is your cube mate. Bob loves to point out each and every little mistake on your web application, even in the middle of development. So it's time to get medieval on Bob and teach him a lesson.

Your task is to write a UDF that will take in a string of HTML. You will then find 10-15 random words that are not inside HTML tags. The words can be wrapped by tags of course, so the words in this block is fine:

view plain print about
1<b>Hendrix is a Cylon</b>

For each word, you will then remove 1-3 random letters and replace it into the original HTML string.

What's going to make this so nice is how you would use this UDF in our hypothetical situation. As you know, Application.cfc's onRequest method can actually modify a request before it is returned to the user. What we would do is simply say:

view plain print about
1<cfif session.username is "bob">
2 <cfset newresult = confusinator(result)>
3 <cfoutput>#newresult#</cfoutput>

Then just sit back and grin as Bob is unable to replicate the bugs on your machine.

Ok guys. Get to it. Let's teach Bob to leave well enough alone.

p.s. In case it isn't clear, you just need to build the UDF. Don't worry about Application.cfc and all that. If you want to build a simple form to let folks type in a URL and see the results, you get bonus points. 2 trillion bonus points will buy you nothing, but Web 2.0 Nothing.


  • Commented on 03-30-2007 at 8:16 AM
    I know this isnt a specific answer to your question, but in the spirit of this friday puzzler, here is an idea to mess with Bob. =)

    Create a folder under a mapped path COM called tagLib
    Make a file under it called a.cfm

    Anywhere you can hide it in his code, add <cfimport taglib="/com/tagLib">

    Now, for the source of a.cfm:

    <cfif thistag.executionMode eq 'Start'><a href=""></cfif>;
    <cfif thistag.executionMode eq 'End'></a></cfif>

    Now watch him rip his (thinning) hair out trying to figure out why his simple non-coldfusion <a href> tags are being re-written. =)
  • Torgo #
    Commented on 03-30-2007 at 8:33 AM
    This is my first time trying out one of the puzzlers. hmm...

    <cffunction name="confusinator" returntype="string" hint="Removes random letters from all words in a string that are not contained within HTML tags">
       <cfargument name="theString" required="yes" type="string">
       <cfloop condition="find('<', theString, 1) NEQ 0">
          <cfset startPos = find('<', theString, 1)>
          <cfset endPos = find('>', theString, startPos) + 1>
          <cfset tagLen = endPos - startPos>
          <cfset theString = removeChars(theString, startPos, tagLen)>
       <cfset newString = listToArray(theString, " ")>
       <cfloop index="theWord" from="1" to="#arrayLen(newString)#">
          <cfset stripCount = randRange(1, 3)>
          <cfloop from="1" to="#stripCount#" index="i">
           <cfif len(newString[theWord]) GT 0>
                <cfset stripChar = randRange(1, len(newString[theWord]))>
                <cfset newString[theWord] = removeChars(newString[theWord], stripChar, 1)>
       <cfset theString = arrayToList(newString, " ")>
       <cfreturn theString>

  • Torgo #
    Commented on 03-30-2007 at 8:35 AM
    Next time, I'll pay attention. I deleted all of the HTML tags out of the string. Oops.
  • Commented on 03-30-2007 at 10:13 AM
    This was a fun way to start my Friday. Here is my contribution.

    code start =======================================

          var theResult = '';
          var bodyFound = 0;
          var scriptHit = 0;
          var randRows = 0;
          var theRows = '';
          total = ListLen(theString, chr(10) & chr(13));
          for (i = 1; i lt total; i = i + 1){
             thisItem = listGetat(theString, i, chr(10) & chr(13));
             if (thisItem does not contain "body" AND NOT bodyFound){
                 // we do not want to muck with anyting till we pass the body tag   
                theResult = theResult & chr(10) & chr(13) & thisItem;         
             } else {
                bodyFound = 1;
                if (randRows EQ 0){         
                   // generate a random row numbers to alter
                   for (r = 1; r lt 50; r = r + 1){
                      thisNum = randRange(i, total);
                      if (listfind(theRows, thisNum)){
                      randRows = listAppend(randRows, thisNum);
             if (thisItem contains "<script" AND Thisitem does not contain "/script"){
                scriptHit = 1; // we do not want to edit the contents of a script
                theResult = theResult & chr(10) & chr(13) & thisItem;
             if (scriptHit AND thisItem contains "/script"){
                scriptHit = 0; // found end of script;
             if (NOT listfind(randRows, i)){
                theResult = theResult & chr(10) & chr(13) & thisItem;         
             noTags = ReReplaceNoCase(thisItem, "<(.|\n)+?>", " ", "ALL");
             if (listLen(noTags, " ")){
                 thisWord = ListGetAt(noTags, RandRange(1, listLen(noTags, " ")), " ");
                 if (len(thisWord) gt 3){
                    newWord = thisWord;
                    for(s=1; s lt randRange(1,3); s = s + 1){
                      newWord = removeChars(newWord, RandRange(1, len(newWord)), 1);
                    thisItem = replace(thisItem, thisWord, newWord);
             theResult = theResult & chr(10) & chr(13) & thisItem;
          return theResult;

    code end =======================================

  • Commented on 03-30-2007 at 10:31 AM
    My Bad. There is a backwards piece if logic.

    Replace this:
    if (scriptHit AND thisItem contains "/script"){
       scriptHit = 0; // found end of script;

    with this:
    if (scriptHit AND thisItem DOES NOT contain "/script"){
       theResult = theResult & chr(10) & chr(13) & thisItem;
    scriptHit = 0; // found end of script;

    Sorry about that.

  • Commented on 03-30-2007 at 10:32 AM
    Here's mine.
    <cffunction name="messWithBob" access="public" returntype="string">
       <cfargument name="textToDestroy" required="true" type="string" />
          var regex="</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>";
          var arModContent = ArrayNew(1);
          var lModContent = REReplaceNoCase(arguments.textToDestroy,regex," ","all");
          var killList = "";
          var wordstokill = 0;
          var numLetters = 0;
          var newWord = "";   
       <cfloop list="#lModContent#" index="i" delimiters=" ">
          <cfif Len(Trim(i))>
             <cfset ArrayAppend(arModContent,i)>
       <cfif ArrayLen(arModContent) GT 15>
          <cfset WordsToKill = RandRange(10,15,"SHA1PRNG")>
          <cfset WordsToKill = RandRange(1,ArrayLen(arModContent),"SHA1PRNG")>
       <cfloop from="1" to="#WordsToKill#" index="j">
          <cfset killWord = RandRange(1,ArrayLen(arModContent),"SHA1PRNG")>
          <cfif NOT ListFindNoCase("cylon,borg",arModContent[killword])>
             <cfset numLetters = RandRange(1,3,"SHA1PRNG")>
             <cfset newWord = arModContent[killword]>
             <cfloop from="1" to="#numLetters#" index="i">
                <cfset newWord = RemoveChars(arModContent[killword],RandRange(1,Len(arModContent[killword]),"SHA1PRNG"),1)>
                <cfif Len(newWord) LT (numLetters - i)>
             <cfset arguments.textToDestroy = Replacenocase(arguments.textToDestroy,arModContent[killword],newWord)>   
             <cfset arguments.textToDestroy = Replacenocase(arguments.textToDestroy,arModContent[killword],"Dalek","all")>
       <cfreturn arguments.textToDestroy />
  • Commented on 03-30-2007 at 1:12 PM
    That was one of the most delightfully evil things I have ever seen.
  • Commented on 03-30-2007 at 3:31 PM
    yeah, I think Justice wins, even though it isn't the real answer. ;) Good responses all though. Shall we mess with Bob again next week as well?
  • Commented on 04-01-2007 at 8:10 PM
    What worries me about this Ray, is that you are the source of so much of the code that people use around the ColdFusion community.

    This isnt to be a "feature" in the next version of Blog.cfc is it??

    Is "Bob" really a code name for "Those mugs in the CF world who dont write their own code but sponge off me instead"??
  • Commented on 04-02-2007 at 8:03 AM
    It is all part of my master plan. ;)
  • Commented on 04-03-2007 at 8:13 AM
    I vote we mess with Bob some more next week. =) It makes it all so much better that I work with a guy named Bob, and I need ways to mess with him!
  • Dan Sorensen #
    Commented on 04-06-2007 at 11:36 AM
    I know this comment is a week late...

    However, I like 'messing with Bob' because ironically you have to understand quite a bit of CF to see what's really going on with these fun little exercises.

    Justice's entry is the kind of evil that would happen in Spy vs. Spy (if they were programmers). ;-)

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty