understanding ColdFusion FindNoCase - coldfusion

I'm going through a coldfusion code and encountered following information. I didn't understand some part of it. My questions are as follows:
CODE:
<cfif FINDNOCASE( "xyz.seta", "#CGI.SERVER_NAME#") GT 0 >
<cfset PublicPath = "abcxyz/NEW_abc/Public">
<cfset SessionPath = "abcxyz/NEW_abc/Session">
I understand that FINDNOCASE is used to find the first occurance of a substring in a string, from a specified start position.
Function Syntax: FindNoCase(substring, string [, start ])
1) So, in my case, xyz.seta substring is searched starting from " #CGI.SERVER_NAME# " ? Am I confused here?
2) Question Regarding the PublicPath and SessionPath defined:
When I checked the server (after logging into it using VNC Viewer), only folders that are visible to me are Public and Session. Where can I find the path before it? Please clarify or let me know if I need to study something more before asking such question.
Thanks

You are correct about your first assumption. The FINDNOCASE will return the index of the start of the sub-string. I think that CF indexes are one based (not 0 based). Thus if the string "xyz.seta" exists in the variable #CGI.SERVERNAME#, the value returned will always be greater than zero and the contents of the CFIF block will execute.
On the variables PublicPath and SessionPath. These variables are page variables as they are not defined by any other scope designation (e.g. session or application). They only exist when this page is processing. If this is in your Application.cfm, it will execute every time this Application.cfm file is called. The values of the variables are being set to paths relative to the the current directory. If you want them absolute, add a slash to the front of the string literals (e.g. "/abcxyz/NEW_abc/Public"). That will make them absolute paths from the document directory of the web server. The web server path varies from OS to OS.

I have no idea what your second question is even asking, let alone the answer, but I can answer the first one.
You are misreading the (fairly clear, I thought) docs for findNoCase().
Function Syntax:
FindNoCase(substring, string [, start ])
Code:
FINDNOCASE( "xyz.seta", "#CGI.SERVER_NAME#")
So xyz.seta is the substring, and CGI.SERVER_NAME is the string. And the optional start attribute is not specified, so is implied to be 1, ie: the beginning of the string.
So the code is looking for xyz.seta within the value of CGI.SERVER_NAME (and will return the position at which it is found, or zero if not found.

This is a pretty simple configuration statement.
If the address that is being accessed (CGI.server_name) at least contains the domain xyx.seta then set these two variables, PublicPath and SessionPath, to be these two values.
I imagine that there is an else that says set the paths to be two different values.
If you look on the server where xyz.seta is hosted you should find those physical file paths.
That's it really. Nothing more nothing less.
You might want to use cfdump and cfabort to umm... dump out the content of CGI scope and variables scope to see what is in there and what is being set. Use cfabort to stop processing immediately after the cfdump.
That should help you to understand what variables are there available to you and what the code above is doing.

FindNoCase(substring, string [, start ])
is the syntax where the "start" is an optional parameter which is not passed here.
The substring "xyz.seta" is searched into the "CGI.SCRIPTNAME". The findnocase function returns 0 if no matches found or a positive number if found(The returned value is the starting index of the substring into the string and the index starts from 1 and not 0). So the statement can be as
<cfif FINDNOCASE( "xyz.seta", "#CGI.SERVER_NAME#")>
as the return value will be positive if matches are found

Related

GoogleTagManager | Parsing URL - With or Without regex

I want to pass into a variable, the language of the user.
But, my client can't/didn't pass this information trough datalayer. So, the unique solution I've is to use the URL Path.
Indeed - The structure is:
http://www.website.be/en/subcategory/subsubcategory
I want to extract "en" information
No idea to get this - I check on Stack, on google, some people talk about regex, other ones about CustomJS, but, no result on my specific setup.
Do you have an idea how to proceed on this point ?
Many thanks !!
Ludo
Make sure the built in {{Page Path}} variable is enabled. Create a custom Javascript variable.
function() {
var parts = {{Page Path}}.split("/");
return parts[1];
}
This splits the path by the path delimiter "/" and gives you an array with the parts. Since the page path has a leading slash (I think), the first part is empty, so you return the second one (since array indexing starts with 0 the second array element has the index 1).
This might need a bit of refinement (for pages that do not start with a language signifier, if any), but that's the basic idea.
Regex is an alternative (via the regex table variable), but the above solution is a little easier to implement.

Is there a way to exact match "truthy" and "falsey" values in ColdFusion

I recently had the need to match against two strings in ColdFusion and ran into this scenario during my loop:
<cfif "0" IS NOT "NO">
Generally during the loop it looks something like this:
<cfif "AM" IS NOT "BA">
Now both of these values were variables (I wasn't just typing it out for fun) and I was using "0" as a default value for the first variable to match against (since the second variables would never be 0) but both of these values changed in the loop I was running. I easily fixed this by setting my default value to -- instead of 0 but I tried researching and found nothing indicating there was a way to get around the falsey nature of strings when evaluating them.
Is there no Operator or trick to match on the strings themselves and ignore their truthyness or falseyness in ColdFusion?
The compare function will help you. This:
writedump(compare("0", "NO"));
returns -1.
This page will tell you what that means.

Setting file paths with Lua/C++

I have xml profiles stored in a folder that are switched dynamically. But the behavior is absolute path and I need a relative path. The lua code is written to work with both windows paths (back slashes) and with mac paths (forward slashes).
On my mac the path might be /folder/folder/profile1.xml. In normal application the program will return a file/location of profile1.xml. And it will find the next profile in the same folder.
If I direct the application to a new folder using a relative link such as ../profile2.xml then the program will find the new profile and returns the file/location as ../profile2.xml. Then it will not find the next profile within the same folder... it's either looking for the next profile out a step (../) or within the original folder as set by the application. I want it to find the next requested profile within this new folder location.
The existing code that sets the current profile and profile path is this:
local loadedprofile = '' --set by application
local profilepath = '' --set by application and modified below
The relevant switching functions seem to be:
local function setDirectory(value)
profilepath = value
end
local function setFile(value)
if loadedprofile ~= value then
doprofilechange(value)
end
end
local function setFullPath(value)
local path, profile = value:match("(.-)([^\\/]-%.?([^%.\\/]*))$")
profilepath = path
if profile ~= loadedprofile then
doprofilechange(profile)
end
I'm thinking I might need to modify the match criteria of the third function to remove the ../. Maybe something like this removing the optional .'s
local function setFullPath(value)
local path, profile = value:match("(.-)([^\\/]-([^%.\\/]*))$")
profilepath = path
if profile ~= loadedprofile then
doprofilechange(profile)
end
I really have no clue as to how to write this code, I'm just trying to tweak this open source code (MIDI2LR) to suit my needs. In my rudimentary understanding of the code it seems the match criteria is overly convoluted. But I would like to know if I am reading it right. I interpret it as:
:match("(.-)([^\\/]-%.?([^%.\\/]*))$")
(.-) --minimal return
( )$ --from the end of profile path
[^\\/]- --starts with \ or \\ or /, 0 or more occurrences first result
%.? --through, with dots optional
[^%.\\/]* --starts with . or \ or \\ or /, 0 or more occurrences all results
If I am reading it right it would seem the first "starts with" is entirely redundant, or that the "from the end" should be associated with the second "starts with."
I have commented out the setFullPath function without the desired results which makes me think that a match requirement might be needed added to the setDirectory function.
Any help is greatly appreciated as I am in way over my head. Thanks!
Your reading of the match is incorrect, here is a more accurate version:
:match("(.-)([^\\/]-%.?([^%.\\/]*))$")
(.-) -- Match and grab everything up until the first non slash character
( )$ -- Grab everything up until the end
[^\\/]- -- Starts with any character OTHER THAN \ or /, 0 or more occurrences first result
%.? -- single dot optional in the middle of the name (for dot in something.ext)
[^%.\\/]* -- Any character OTHER THAN . or \ or /, 0 or more occurrences
A few notes - %. is a literal dot. [^xyz] is the inverse class, so every character other than x, y, or z. \\ is actually just one backslash, this is due to the escaping in a string.
This simpler version would break it in a similar way that is easier to work with: value:match("(.-)([^\\/]+)$")
You may want to provide more information on the profile loading behavior, its hard to tell what you need the code to do. What value would path and profile have in the example you give?

How to create a regex to check whether a set of words exists in a given string?

How can I write a regex to check if a set of words exist in a given string?
For example, I would like to check if a domain name contains "yahoo.com" at the end of it.
'answers.yahoo.com', would be valid.
'yahoo.com.answers', would be wrong. 'yahoo.com' must come in the end.
I got a hint from somewhere that it might be something like this.
"/^[^yahoo.com]$/"
But I am totally new to regex. So please help with this one, then I can learn further.
When asking regex questions, always specify the language or application, too!
From your history it looks like JavaScript / jQuery is most likely.
Anyway, to test that a string ends in "yahoo.com" use /.*yahoo\.com$/i
In JS code:
if (/.*yahoo\.com$/i.test (YOUR_STR) ) {
//-- It's good.
}
To test whether a set of words has at least one match, use:
/word_one|word_two|word_three/
To limit matches to just the most-common, legal sub-domains, ending with "yahoo.com", use:
/^(\w+\.)+yahoo\.com$/
(As a crude, first pass)
For other permutations, please clarify the question.

Tokenize the text depending on some specific rules. Algorithm in C++

I am writing a program which will tokenize the input text depending upon some specific rules. I am using C++ for this.
Rules
Letter 'a' should be converted to token 'V-A'
Letter 'p' should be converted to token 'C-PA'
Letter 'pp' should be converted to token 'C-PPA'
Letter 'u' should be converted to token 'V-U'
This is just a sample and in real time I have around 500+ rules like this. If I am providing input as 'appu', it should tokenize like 'V-A + C-PPA + V-U'. I have implemented an algorithm for doing this and wanted to make sure that I am doing the right thing.
Algorithm
All rules will be kept in a XML file with the corresponding mapping to the token. Something like
<rules>
<rule pattern="a" token="V-A" />
<rule pattern="p" token="C-PA" />
<rule pattern="pp" token="C-PPA" />
<rule pattern="u" token="V-U" />
</rules>
1 - When the application starts, read this xml file and keep the values in a 'std::map'. This will be available until the end of the application(singleton pattern implementation).
2 - Iterate the input text characters. For each character, look for a match. If found, become more greedy and look for more matches by taking the next characters from the input text. Do this until we are getting a no match. So for the input text 'appu', first look for a match for 'a'. If found, try to get more match by taking the next character from the input text. So it will try to match 'ap' and found no matches. So it just returns.
3 - Replace the letter 'a' from input text as we got a token for it.
4 - Repeat step 2 and 3 with the remaining characters in the input text.
Here is a more simple explanation of the steps
input-text = 'appu'
tokens-generated=''
// First iteration
character-to-match = 'a'
pattern-found = true
// since pattern found, going recursive and check for more matches
character-to-match = 'ap'
pattern-found = false
tokens-generated = 'V-A'
// since no match found for 'ap', taking the first success and replacing it from input text
input-text = 'ppu'
// second iteration
character-to-match = 'p'
pattern-found = true
// since pattern found, going recursive and check for more matches
character-to-match = 'pp'
pattern-found = true
// since pattern found, going recursive and check for more matches
character-to-match = 'ppu'
pattern-found = false
tokens-generated = 'V-A + C-PPA'
// since no match found for 'ppu', taking the first success and replacing it from input text
input-text = 'u'
// third iteration
character-to-match = 'u'
pattern-found = true
tokens-generated = 'V-A + C-PPA + V-U' // we'r done!
Questions
1 - Is this algorithm looks fine for this problem or is there a better way to address this problem?
2 - If this is the right method, std::map is a good choice here? Or do I need to create my own key/value container?
3 - Is there a library available which can tokenize string like the above?
Any help would be appreciated
:)
So you're going through all of the tokens in your map looking for matches? You might as well use a list or array, there; it's going to be an inefficient search regardless.
A much more efficient way of finding just the tokens suitable for starting or continuing a match would be to store them as a trie. A lookup of a letter there would give you a sub-trie which contains only the tokens which have that letter as the first letter, and then you just continue searching downward as far as you can go.
Edit: let me explain this a little further.
First, I should explain that I'm not familiar with these the C++ std::map, beyond the name, which makes this a perfect example of why one learns the theory of this stuff as well as than details of particular libraries in particular programming languages: unless that library is badly misusing the name "map" (which is rather unlikely), the name itself tells me a lot about the characteristics of the data structure. I know, for example, that there's going to be a function that, given a single key and the map, will very efficiently search for and return the value associated with that key, and that there's also likely a function that will give you a list/array/whatever of all of the keys, which you could search yourself using your own code.
My interpretation of your data structure is that you have a map where the keys are what you call a pattern, those being a list (or array, or something of that nature) of characters, and the values are tokens. Thus, you can, given a full pattern, quickly find the token associated with it.
Unfortunately, while such a map is a good match to converting your XML input format to a internal data structure, it's not a good match to the searches you need to do. Note that you're not looking up entire patterns, but the first character of a pattern, producing a set of possible tokens, followed by a lookup of the second character of a pattern from within the set of patterns produced by that first lookup, and so on.
So what you really need is not a single map, but maps of maps of maps, each keyed by a single character. A lookup of "p" on the top level should give you a new map, with two keys: p, producing the C-PPA token, and "anything else", producing the C-PA token. This is effectively a trie data structure.
Does this make sense?
It may help if you start out by writing the parsing code first, in this manner: imagine someone else will write the functions to do the lookups you need, and he's a really good programmer and can do pretty much any magic that you want. Writing the parsing code, concentrate on making that as simple and clean as possible, creating whatever interface using these arbitrary functions you need (while not getting trivial and replacing the whole thing with one function!). Now you can look at the lookup functions you ended up with, and that tells you how you need to access your data structure, which will lead you to the type of data structure you need. Once you've figured that out, you can then work out how to load it up.
This method will work - I'm not sure that it is efficient, but it should work.
I would use the standard std::map rather than your own system.
There are tools like lex (or flex) that can be used for this. The issue would be whether you can regenerate the lexical analyzer that it would construct when the XML specification changes. If the XML specification does not change often, you may be able to use tools such as lex to do the scanning and mapping more easily. If the XML specification can change at the whim of those using the program, then lex is probably less appropriate.
There are some caveats - notably that both lex and flex generate C code, rather than C++.
I would also consider looking at pattern matching technology - the sort of stuff that egrep in particular uses. This has the merit of being something that can be handled at runtime (because egrep does it all the time). Or you could go for a scripting language - Perl, Python, ... Or you could consider something like PCRE (Perl Compatible Regular Expressions) library.
Better yet, if you're going to use the boost library, there's always the Boost tokenizer library -> http://www.boost.org/doc/libs/1_39_0/libs/tokenizer/index.html
You could use a regex (perhaps the boost::regex library). If all of the patterns are just strings of letters, a regex like "(a|p|pp|u)" would find a greedy match. So:
Run a regex_search using the above pattern to locate the next match
Plug the match-text into your std::map to get the replace-text.
Print the non-matched consumed input and replace-text to your output, then repeat 1 on the remaining input.
And done.
It may seem a bit complicated, but the most efficient way to do that is to use a graph to represent a state-chart. At first, i thought boost.statechart would help, but i figured it wasn't really appropriate. This method can be more efficient that using a simple std::map IF there are many rules, the number of possible characters is limited and the length of the text to read is quite high.
So anyway, using a simple graph :
0) create graph with "start" vertex
1) read xml configuration file and create vertices when needed (transition from one "set of characters" (eg "pp") to an additional one (eg "ppa")). Inside each vertex, store a transition table to the next vertices. If "key text" is complete, mark vertex as final and store the resulting text
2) now read text and interpret it using the graph. Start at the "start" vertex. ( * ) Use table to interpret one character and to jump to new vertex. If no new vertex has been selected, an error can be issued. Otherwise, if new vertex is final, print the resulting text and jump back to start vertex. Go back to (*) until there is no more text to interpret.
You could use boost.graph to represent the graph, but i think it is overly complex for what you need. Make your own custom representation.