diff options
author | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
commit | 302bf1b523012e11b60425d6eee1221ebc2724eb (patch) | |
tree | b191a895f8716efcbe42f454f37597a545a6f421 /mailnews/addrbook/src/nsAbQueryStringToExpression.cpp | |
parent | 21b3f6247403c06f85e1f45d219f87549862198f (diff) | |
download | UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip |
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/addrbook/src/nsAbQueryStringToExpression.cpp')
-rw-r--r-- | mailnews/addrbook/src/nsAbQueryStringToExpression.cpp | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/mailnews/addrbook/src/nsAbQueryStringToExpression.cpp b/mailnews/addrbook/src/nsAbQueryStringToExpression.cpp new file mode 100644 index 000000000..fe1f22e00 --- /dev/null +++ b/mailnews/addrbook/src/nsAbQueryStringToExpression.cpp @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsAbQueryStringToExpression.h" + +#include "nsComponentManagerUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsStringGlue.h" +#include "nsITextToSubURI.h" +#include "nsAbBooleanExpression.h" +#include "nsAbBaseCID.h" +#include "plstr.h" +#include "nsIMutableArray.h" + +/** + * This code parses the query expression passed in as an addressbook URI. + * The expression takes the form: + * (BOOL1(FIELD1,OP1,VALUE1)..(FIELDn,OPn,VALUEn)(BOOL2(FIELD1,OP1,VALUE1)...)...) + * + * BOOLn A boolean operator joining subsequent terms delimited by (). + * For possible values see CreateBooleanExpression(). + * FIELDn An addressbook card data field. + * OPn An operator for the search term. + * For possible values see CreateBooleanConditionString(). + * VALUEn The value to be matched in the FIELDn via the OPn operator. + * The value must be URL encoded by the caller, if it contains any special + * characters including '(' and ')'. + */ +nsresult nsAbQueryStringToExpression::Convert ( + const nsACString &aQueryString, + nsIAbBooleanExpression** expression) +{ + nsresult rv; + + nsAutoCString q(aQueryString); + q.StripWhitespace(); + const char *queryChars = q.get(); + + nsCOMPtr<nsISupports> s; + rv = ParseExpression(&queryChars, getter_AddRefs(s)); + NS_ENSURE_SUCCESS(rv, rv); + + // Case: Not end of string + if (*queryChars != 0) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsIAbBooleanExpression> e(do_QueryInterface(s, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*expression = e); + return rv; +} + +nsresult nsAbQueryStringToExpression::ParseExpression ( + const char** index, + nsISupports** expression) +{ + nsresult rv; + + if (**index != '(') + return NS_ERROR_FAILURE; + + const char* indexBracket = *index + 1; + while (*indexBracket && + *indexBracket != '(' && *indexBracket != ')') + indexBracket++; + + // Case: End of string + if (*indexBracket == 0) + return NS_ERROR_FAILURE; + + // Case: "((" or "()" + if (indexBracket == *index + 1) + { + return NS_ERROR_FAILURE; + } + // Case: "(*(" + else if (*indexBracket == '(') + { + // printf ("Case: (*(: %s\n", *index); + + nsCString operation; + rv = ParseOperationEntry ( + *index, indexBracket, + getter_Copies (operation)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIAbBooleanExpression> e; + rv = CreateBooleanExpression(operation.get(), + getter_AddRefs(e)); + NS_ENSURE_SUCCESS(rv, rv); + + // Case: "(*)(*)....(*))" + *index = indexBracket; + rv = ParseExpressions (index, e); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*expression = e); + } + // Case" "(*)" + else if (*indexBracket == ')') + { + // printf ("Case: (*): %s\n", *index); + + nsCOMPtr<nsIAbBooleanConditionString> conditionString; + rv = ParseCondition (index, indexBracket, + getter_AddRefs(conditionString)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*expression = conditionString); + } + + if (**index != ')') + return NS_ERROR_FAILURE; + + (*index)++; + + return NS_OK; +} + + +nsresult nsAbQueryStringToExpression::ParseExpressions ( + const char** index, + nsIAbBooleanExpression* expression) +{ + nsresult rv; + nsCOMPtr<nsIMutableArray> expressions(do_CreateInstance(NS_ARRAY_CONTRACTID, + &rv)); + if (NS_FAILED(rv)) + return NS_ERROR_OUT_OF_MEMORY; + + // Case: ")(*)(*)....(*))" + // printf ("Case: )(*)(*)....(*)): %s\n", *index); + while (**index == '(') + { + nsCOMPtr<nsISupports> childExpression; + rv = ParseExpression(index, getter_AddRefs (childExpression)); + NS_ENSURE_SUCCESS(rv, rv); + + expressions->AppendElement(childExpression, false); + } + + if (**index == 0) + return NS_ERROR_FAILURE; + + // Case: "))" + // printf ("Case: )): %s\n", *index); + + if (**index != ')') + return NS_ERROR_FAILURE; + + expression->SetExpressions (expressions); + + return NS_OK; +} + +nsresult nsAbQueryStringToExpression::ParseCondition ( + const char** index, + const char* indexBracketClose, + nsIAbBooleanConditionString** conditionString) +{ + nsresult rv; + + (*index)++; + + nsCString entries[3]; + for (int i = 0; i < 3; i++) + { + rv = ParseConditionEntry (index, indexBracketClose, + getter_Copies (entries[i])); + NS_ENSURE_SUCCESS(rv, rv); + + if (*index == indexBracketClose) + break; + } + + if (*index != indexBracketClose) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsIAbBooleanConditionString> c; + rv = CreateBooleanConditionString ( + entries[0].get(), + entries[1].get(), + entries[2].get(), + getter_AddRefs (c)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*conditionString = c); + return NS_OK; +} + +nsresult nsAbQueryStringToExpression::ParseConditionEntry ( + const char** index, + const char* indexBracketClose, + char** entry) +{ + const char* indexDeliminator = *index; + while (indexDeliminator != indexBracketClose && + *indexDeliminator != ',') + indexDeliminator++; + + int entryLength = indexDeliminator - *index; + if (entryLength) + *entry = PL_strndup (*index, entryLength); + else + *entry = 0; + + if (indexDeliminator != indexBracketClose) + *index = indexDeliminator + 1; + else + *index = indexDeliminator; + + return NS_OK; +} + +nsresult nsAbQueryStringToExpression::ParseOperationEntry ( + const char* indexBracketOpen1, + const char* indexBracketOpen2, + char** operation) +{ + int operationLength = indexBracketOpen2 - indexBracketOpen1 - 1; + if (operationLength) + *operation = PL_strndup (indexBracketOpen1 + 1, + operationLength); + else + *operation = 0; + + return NS_OK; +} + +nsresult nsAbQueryStringToExpression::CreateBooleanExpression( + const char* operation, + nsIAbBooleanExpression** expression) +{ + nsAbBooleanOperationType op; + if (PL_strcasecmp (operation, "and") == 0) + op = nsIAbBooleanOperationTypes::AND; + else if (PL_strcasecmp (operation, "or") == 0) + op = nsIAbBooleanOperationTypes::OR; + else if (PL_strcasecmp (operation, "not") == 0) + op = nsIAbBooleanOperationTypes::NOT; + else + return NS_ERROR_FAILURE; + + nsresult rv; + + nsCOMPtr <nsIAbBooleanExpression> expr = do_CreateInstance(NS_BOOLEANEXPRESSION_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + NS_IF_ADDREF(*expression = expr); + + rv = expr->SetOperation (op); + return rv; +} + +nsresult nsAbQueryStringToExpression::CreateBooleanConditionString ( + const char* attribute, + const char* condition, + const char* value, + nsIAbBooleanConditionString** conditionString) +{ + if (attribute == 0 || condition == 0 || value == 0) + return NS_ERROR_FAILURE; + + nsAbBooleanConditionType c; + + if (PL_strcasecmp (condition, "=") == 0) + c = nsIAbBooleanConditionTypes::Is; + else if (PL_strcasecmp (condition, "!=") == 0) + c = nsIAbBooleanConditionTypes::IsNot; + else if (PL_strcasecmp (condition, "lt") == 0) + c = nsIAbBooleanConditionTypes::LessThan; + else if (PL_strcasecmp (condition, "gt") == 0) + c = nsIAbBooleanConditionTypes::GreaterThan; + else if (PL_strcasecmp (condition, "bw") == 0) + c = nsIAbBooleanConditionTypes::BeginsWith; + else if (PL_strcasecmp (condition, "ew") == 0) + c = nsIAbBooleanConditionTypes::EndsWith; + else if (PL_strcasecmp (condition, "c")== 0) + c = nsIAbBooleanConditionTypes::Contains; + else if (PL_strcasecmp (condition, "!c") == 0) + c = nsIAbBooleanConditionTypes::DoesNotContain; + else if (PL_strcasecmp (condition, "~=") == 0) + c = nsIAbBooleanConditionTypes::SoundsLike; + else if (PL_strcasecmp (condition, "regex") == 0) + c = nsIAbBooleanConditionTypes::RegExp; + else + return NS_ERROR_FAILURE; + + nsresult rv; + + nsCOMPtr<nsIAbBooleanConditionString> cs = do_CreateInstance(NS_BOOLEANCONDITIONSTRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = cs->SetCondition (c); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsITextToSubURI> textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID,&rv); + if (NS_SUCCEEDED(rv)) + { + nsString attributeUCS2; + nsString valueUCS2; + + rv = textToSubURI->UnEscapeAndConvert("UTF-8", + attribute, getter_Copies(attributeUCS2)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = textToSubURI->UnEscapeAndConvert("UTF-8", + value, getter_Copies(valueUCS2)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ConvertUTF16toUTF8 attributeUTF8(attributeUCS2); + + rv = cs->SetName (attributeUTF8.get ()); + NS_ENSURE_SUCCESS(rv, rv); + rv = cs->SetValue(valueUCS2.get()); + NS_ENSURE_SUCCESS(rv, rv); + } + else + { + NS_ConvertUTF8toUTF16 valueUCS2(value); + + rv = cs->SetName (attribute); + NS_ENSURE_SUCCESS(rv, rv); + rv = cs->SetValue (valueUCS2.get ()); + NS_ENSURE_SUCCESS(rv, rv); + } + + + NS_IF_ADDREF(*conditionString = cs); + return NS_OK; +} + + |