Product Documentation

Complex Operations on Text

Aug 31, 2016

In addition to performing simple string matching, you can configure expressions that examine more complex aspects of text, including examining the length of a string and looking within a text block for patterns rather than specific strings.

Be aware of the following for any text-based operation:

  • For any operation that takes a string argument, the string cannot exceed 255 characters.
  • You can include white space when you specify a string in an expression.

Operations on the Length of a String

The following operations extract strings on the basis of a character count.

Table 1. String Operations Based on a Character Count

Character Count Operation

Description

<text>.TRUNCATE(<count>)

Returns a string after truncating the end of the target by the number of characters in <count>.

If the entire string is shorter than <count>, nothing is returned.

<text>.TRUNCATE(<character>, <count>)

Returns a string after truncating the text after <character> by the number of characters specified in <count>.

<text>.PREFIX(<character>, <count>)

Selects the longest prefix in the target that has at most <count> occurrences of <character>.

<text>.SUFFIX(<character>, <count>) Selects the longest suffix in the target that has at most <count> occurrences of <character>.

For example, consider the following response body:

JLEwx

The following expression returns a value of “JLEwx”:

http.res.body(100).suffix('L',1)

The following expression returns “LLEwx”:

http.res.body(100).suffix('L',2)

<text>.SUBSTR(<starting_offset>, <length>)

Select a string with <length> number of characters from the target object. Begin extracting the string after the <starting_offset>. If the number of characters after the offset are fewer than the value of the <length> argument, select all the remaining characters.

<text>.SKIP(<character>, <count>)

Select a string from the target after skipping over the longest prefix that has at most <count> occurrences of <character>.

Operations on a Portion of a String

You can extract a subset of a larger string by using one of the operations in the following table.

Table 2. Basic Operations on a Portion of a String

Basic Text Operation

Description

<text>.BEFORE_STR(<string>)

Returns the text that precedes the first occurrence of <string>.

If there is no match for <string>, the expression returns a text object of 0 length.

Following is an example:

http.res.body(1024).after_str("start_string").before_str("end_string").contains("https")

<text>.AFTER_STR(<string>)

Returns the text that follows the first occurrence of <string>.

If there is no match for <string>, the expression returns a text object of 0 length.

Following is an example:

http.res.body(1024).after_str("start_string").before_str("end_string").contains("https")

<text>.BETWEEN(<starting string>, <ending string>)

Returns a Boolean TRUE value if the length of the text object is greater than or equal to the sum <starting string>, <ending string> argument lengths, and if a prefix of the target matches <starting string>, and if the suffix of the target matches <ending string>.

<text>.PREFIX(<prefix length>)

Returns the starting string from a target block of text that contains the number of characters in the <prefix length> argument.

If the <prefix length> argument exceeds the number of characters in the target, the entire string is selected.

<text>.SUFFIX(<suffix length>)

Returns the ending string from a target block of text that contains the number of characters in the <suffix length> argument. If the <suffix length> argument exceeds the number characters in the target, the entire string is selected.

<text>.SUBSTR(<string>)

Select the first block of text in the target that matches the <string>.

<text>.SKIP(<prefix length>)

Selects the text in the target after skipping over a <prefix length> number of characters.

If the entire target has fewer characters than <prefix length>, the entire target is skipped.

<text>.STRIP_END_WS

Selects the text after removing white space from the end of the target.

<text>.STRIP_START_WS

Selects the text after removing white space from the beginning of the target.

<text>.UNQUOTE(<character>)

Selects the <character>, removes white space that immediately precedes and follows the <character>, and if the remaining text is quoted by <character>, this prefix also removes the quotes.

For example, the operation UNQUOTE('"') changes the following text:

"abc xyz def "

To the following:

abc xyz def

Operations for Comparing the Alphanumeric Order of Two Strings

The COMPARE operation examines the first nonmatching character of two different strings. This operation is based on lexicographic order, which is the method used when ordering terms in dictionaries.

This operation returns the arithmetic difference between the ASCII values of the first nonmatching characters in the compared strings. The following differences are examples:

  • The difference between “abc” and “abd” is -1 (based on the third pair-wise character comparison).
  • The difference between “@” and “abc” is -33.
  • The difference between “1” and “abc” is -47.

Following is the syntax for the COMPARE operation.

<text>.COMPARE(<string>)

Extracting an Integer from a String of Bytes That Represent Text

You can use the following functions to treat a string of bytes that represent text as a sequence of bytes, extract 8, 16, or 32 bits from the sequence, and then convert the extracted bits to an integer.

Table 3. Operations for Extracting an Integer from a String of Bytes That Represent Text

Function

Description

<text>.GET_SIGNED8(<n>)

Treats the string of bytes represented by text as a sequence of 8-bit signed integers and returns the integer at byte offset n. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

<text>.GET_UNSIGNED8(<n>)

Treats the string of bytes represented by text as a sequence of 8-bit unsigned integers and returns the integer at byte offset n. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

<text>.GET_SIGNED16(<n>, <endianness>)

Treats the text string returned by the prefix as a string of bytes, extracts 16 bits starting at byte offset n, and converts the extracted bit sequence to a 16-bit signed integer. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

The first parameter n is the byte offset from the current position in the text string. Providing a byte offset enables the function to handle items that are not aligned on the boundaries that are required by indexes. The second parameter, endianness, takes a mnemonic value of LITTLE_ENDIAN or BIG_ENDIAN.

Note: In NetScaler 9.2, the parameter n was an index into an array of 16-bit items. In NetScaler 9.3, the parameter is a byte offset. Therefore, if you used this function in NetScaler 9.2, after you upgrade to NetScaler 9.3, you must change n to 2*n to obtain the same results as you did earlier. For example, if the value of n before the upgrade was 4, you must change the value of n to 8. The parameter endianness also no longer takes the values that it did in NetScaler 9.2, which were 0 and 1. Instead, endianness accepts the mnemonic values mentioned earlier.

Example

HTTP.REQ.BODY(100).GET_SIGNED16(8, BIG_ENDIAN)

<text>.GET_UNSIGNED16(<n>, <endianness>)

Treats the text string returned by the prefix as a string of bytes, extracts 16 bits starting at byte offset n, and converts the extracted bit sequence to a 16-bit unsigned integer. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

The first parameter n is the byte offset from the current position in the text string. Providing a byte offset enables the function to handle items that are not aligned on the boundaries that are required by indexes. The second parameter, endianness, takes a mnemonic value of LITTLE_ENDIAN or BIG_ENDIAN.

Note: In NetScaler 9.2, the parameter n was an index into an array of 16-bit items. In NetScaler 9.3, the parameter is a byte offset. Therefore, if you used this function in NetScaler 9.2, after you upgrade to NetScaler 9.3, you must change n to 2*n to obtain the same results as you did earlier. For example, if the value of n before the upgrade was 4, you must change the value of n to 8. The parameter endianness also no longer takes the values that it did in NetScaler 9.2, which were 0 and 1. Instead, endianness accepts the mnemonic values mentioned earlier.

Example

HTTP.REQ.BODY(100).GET_UNSIGNED16(8, LITTLE_ENDIAN)

<text>.GET_SIGNED32(<n>, <endianness>)

Treats the text string returned by the prefix as a string of bytes, extracts 32 bits starting at byte offset n, and converts the extracted bit sequence to a 32-bit signed integer. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

The first parameter n is the byte offset from the current position in the text string. Providing a byte offset enables the function to handle items that are not aligned on the boundaries that are required by indexes. The second parameter, endianness, takes a mnemonic value of LITTLE_ENDIAN or BIG_ENDIAN.

Note: In NetScaler 9.2, the parameter n was an index into an array of 32-bit items. In NetScaler 9.3, the parameter is a byte offset. Therefore, if you used this function in NetScaler 9.2, after you upgrade to NetScaler 9.3, you must change n to 4*n to obtain the same results as you did earlier. For example, if the value of n before the upgrade was 4, you must change the value of n to 16. The parameter endianness also no longer takes the values that it did in NetScaler 9.2, which were 0 and 1. Instead, endianness accepts the mnemonic values mentioned earlier.

Example

HTTP.REQ.BODY(1000).GET_SIGNED32(12, BIG_ENDIAN)

<text>.GET_UNSIGNED32(<n>, <endianness>)

Treats the text string returned by the prefix as a string of bytes, extracts 32 bits starting at byte offset n, and returns the extracted bit sequence as part of a 64-bit unsigned long integer. If the offset makes all or part of the value outside of the current text, an UNDEF condition is raised.

The first parameter n is the byte offset from the current position in the text string. Providing a byte offset enables the function to handle items that are not aligned on the boundaries that are required by indexes. The second parameter, endianness, takes a mnemonic value of LITTLE_ENDIAN or BIG_ENDIAN.

Example

HTTP.REQ.BODY(1000).GET_UNSIGNED32(30, LITTLE_ENDIAN)

Converting Text to a Hash Value

You can convert a text string to a hash value by using the HASH function. This function returns a 31-bit positive integer as a result of the operation. Following is the format of the expression:

<text>.HASH

This function ignores case and white spaces. For example, after the operation, the two strings Ab c and a bc would produce the same hash value.

Encoding and Decoding Text by Applying the Base64 Encoding Algorithm

The following two functions encode and decode a text string by applying the Base64 encoding algorithm

Table 4. Functions for Encoding and Decoding a Text String by Using Base64 Encoding

Function

Description

text.B64ENCODE

Encodes the text string (designated by text) by applying the Base64 encoding algorithm.

text.B64DECODE

Decodes the Base64-encoded string (designated by text) by applying the Base64 decoding algorithm. The operation raises an UNDEF if text is not in B64-encoded format.

Refining the Search in a Rewrite Action by Using the EXTEND Function

The EXTEND function is used in rewrite actions that specify patterns or pattern sets and target the bodies of HTTP packets. When a pattern match is found, the EXTEND function extends the scope of the search by a predefined number of bytes on both sides of the matching string. A regular expression can then be used to perform a rewrite on matches in this extended region. Rewrite actions that are configured with the EXTEND function perform rewrites faster than rewrite actions that evaluate entire HTTP bodies using only regular expressions.

The format of the EXTEND function is EXTEND(m,n ), where m and n are the number of bytes by which the scope of the search is extended before and after the matching pattern, respectively. When a match is found, the new search scope comprises m bytes that immediately precede the matching string, the string itself, and the n bytes that follow the string. A regular expression can then be used to perform a rewrite on a portion of this new string.

The EXTEND function can be used only if the rewrite action in which it is used fulfills the following requirements:

  • The search is performed by using patterns or patterns sets (not regular expressions)
  • The rewrite action evaluates only the bodies of HTTP packets.

Additionally, the EXTEND function can be used only with the following types of rewrite actions:

  • replace_all
  • insert_after_all
  • delete_all
  • insert_before_all

For example, you might want to delete all instances of "http://exampleurl.com/" and "http://exampleurl.au/" in the first 1000 bytes of the body. To do this, you can configure a rewrite action to search for all instances of the string exampleurl, extend the scope of the search on both sides of the string when a match is found, and then use a regular expression to perform the rewrite in the extended region. The following example extends the scope of the search by 20 bytes to the left and 50 bytes to the right of the matching string:

add rewrite action delurl_example delete_all 'HTTP.REQ.BODY(1000)' -pattern exampleurl -refineSearch 'extend(20,50).regex_select(re#http://exampleurl.(com|au)#)'

Converting Text to Hexadecimal Format

The following function converts text to hexadecimal format and extracts the resulting string:

<text>.BLOB_TO_HEX(<string>)

For example, this function converts the byte string “abc” to “61:62:63”.

Encrypting and Decrypting Text

Updated: 2013-09-02

In default syntax expressions, you can use the ENCRYPT and DECRYPT functions to encrypt and decrypt text. Data encrypted by the ENCRYPT function on a given NetScaler appliance or high availability (HA) pair is intended for decryption by the DECRYPT function on the same NetScaler appliance or HA pair. The appliance supports the RC4, DES3, AES128, AES192, and AES256 encryption methods. The key value that is required for encryption is not user-specifiable. When an encryption method is set, the appliance automatically generates a random key value that is appropriate for the specified method. The default method is AES256 encryption, which is the most secure encryption method and the one that Citrix recommends.

You do not need to configure encryption unless you want to change the encryption method or you want the appliance to generate a new key value for the current encryption method.

Note: You can also encrypt and decrypt XML payloads. For information about the functions for encrypting and decrypting XML payloads, see "Encrypting and Decrypting XML Payloads."

Configuring Encryption

Updated: 2013-09-02

During startup, the appliance runs the set ns encryptionParams command with, by default, the AES256 encryption method, and uses a randomly generated key value that is appropriate for AES256 encryption. The appliance also encrypts the key value and saves the command, with the encrypted key value, to the NetScaler configuration file. Consequently, the AES256 encryption method is enabled for the ENCRYPT and DECRYPT functions by default. The key value that is saved in the configuration file persists across reboots even though the appliance runs the command each time you restart it.

You can run the set ns encryptionParams command manually, or use the configuration utility, if you want to change the encryption method or if you want the appliance to generate a new key value for the current encryption method. To use the CLI to change the encryption method, set only the method parameter, as shown in "Example 1: Changing the Encryption Method." If you want the appliance to generate a new key value for the current encryption method, set the method parameter to the current encryption method and the keyValue parameter to an empty string (""), as shown in "Example 2: Generating a New Key Value for the Current Encryption Method." After you generate a new key value, you must save the configuration. If you do not save the configuration, the appliance uses the newly generated key value only until the next restart, after which it reverts to the key value in the saved configuration.

To configure encryption by using the configuration utility

  1. Navigate to System > Settings.
  2. In the Settings area, click Change Encryption parameters.
  3. In the Change Encryption Parameters dialog box, do one of the following:
    • To change the encryption method, in the Method list, select the encryption method that you want.
    • To generate a new key value for the current encryption method, click Generate a new key for the selected method.
  4. Click OK.

Using the ENCRYPT and DECRYPT Functions

You can use the ENCRYPT and DECRYPT functions with any expression prefix that returns text. For example, you can use the ENCRYPT and DECRYPT functions in rewrite policies for cookie encryption. In the following example, the rewrite actions encrypt a cookie named MyCookie, which is set by a back-end service, and decrypt the same cookie when it is returned by a client:

add rewrite action my-cookie-encrypt-action replace "HTTP.RES.SET_COOKIE.COOKIE(\"MyCookie\").VALUE(0)" "HTTP.RES.SET_COOKIE.COOKIE(\"MyCookie\").VALUE(0).ENCRYPT" -bypassSafetyCheck YES

add rewrite action my-cookie-decrypt-action replace "HTTP.REQ.COOKIE.VALUE(\"MyCookie\")" "HTTP.REQ.COOKIE.VALUE(\"MyCookie\").DECRYPT" -bypassSafetyCheck YES

After you configure policies for encryption and decryption, save the configuration to bring the policies into effect.