Skip to content

Commit 0a7948e

Browse files
authored
Merge pull request #18 from DirectProjectJavaRI/develop
Releasing 8.1.2
2 parents dab5588 + f0d408c commit 0a7948e

File tree

5 files changed

+150
-12
lines changed

5 files changed

+150
-12
lines changed

pom.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<artifactId>direct-policy</artifactId>
66
<name>Direct Project policy enablement engine</name>
7-
<version>8.1.0</version>
7+
<version>8.1.2</version>
88
<description>Direct Project policy enablement engine</description>
99
<inceptionYear>2010</inceptionYear>
1010
<url>http://api.nhindirect.org/x/www/api.nhindirect.org/java/site/direct-policy/${project.version}</url>
@@ -204,7 +204,6 @@
204204
</execution>
205205
</executions>
206206
</plugin>
207-
<!-- for release only
208207
<plugin>
209208
<groupId>org.apache.maven.plugins</groupId>
210209
<artifactId>maven-gpg-plugin</artifactId>
@@ -219,7 +218,6 @@
219218
</executions>
220219
<version>3.0.1</version>
221220
</plugin>
222-
-->
223221
<plugin>
224222
<groupId>org.sonatype.central</groupId>
225223
<artifactId>central-publishing-maven-plugin</artifactId>

src/main/java/org/nhindirect/policy/impl/SimpleTextV1LexiconPolicyParser.java

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ public class SimpleTextV1LexiconPolicyParser extends XMLLexiconPolicyParser
169169
tokenMap = new HashMap<String, TokenType>();
170170

171171
// build the token list
172+
// Note: do not add a raw quote token here. Quoted text is handled specially in parseToTokens.
172173
tokenMap.put("(", TokenType.START_LEVEL);
173174
tokenMap.put(")", TokenType.END_LEVEL);
174175

@@ -180,7 +181,7 @@ public class SimpleTextV1LexiconPolicyParser extends XMLLexiconPolicyParser
180181
// add the X509Fields
181182
tokenMap.put(X509FieldType.SIGNATURE.getFieldToken(), TokenType.CERTIFICATE_REFERENCE_EXPRESSION);
182183
tokenMap.put(X509FieldType.SIGNATURE_ALGORITHM.getFieldToken(), TokenType.CERTIFICATE_REFERENCE_EXPRESSION);
183-
184+
184185
// add the TBS fields
185186
final TBSFieldName[] tbsFieldNames = (TBSFieldName[].class.cast(TBSFieldName.class.getEnumConstants()));
186187
for (TBSFieldName tbsFieldName : tbsFieldNames)
@@ -489,17 +490,75 @@ protected Vector<TokenTypeAssociation> parseToTokens(InputStream stream) throws
489490
boolean holdMode = false;
490491
TokenType holdType = null;
491492

492-
for (int i; (i = isr.read()) > 0; )
493+
for (int ci; (ci = isr.read()) != -1; )
493494
{
494-
writer.write(i);
495+
final char ch = (char)ci;
496+
497+
// If we encounter an opening quote, flush any buffered text and read until the closing quote.
498+
if (ch == '"')
499+
{
500+
final String pre = writer.toString().trim();
501+
if (!pre.isEmpty())
502+
{
503+
final TokenType exactPreToken = tokenMap.get(pre);
504+
final TokenType addPreType = (exactPreToken != null) ? exactPreToken : TokenType.LITERAL_EXPRESSION;
505+
tokens.add(new TokenTypeAssociation(pre, addPreType));
506+
}
507+
writer = new StringWriter();
508+
509+
// read until closing quote or EOF; everything inside is a literal expression
510+
StringBuilder quoted = new StringBuilder();
511+
int cj;
512+
while ((cj = isr.read()) != -1)
513+
{
514+
final char qc = (char)cj;
515+
// handle escape sequences
516+
if (qc == '\\')
517+
{
518+
int nd = isr.read();
519+
if (nd == -1)
520+
{
521+
// dangling backslash at EOF; treat the backslash literally
522+
quoted.append('\\');
523+
break;
524+
}
525+
final char esc = (char)nd;
526+
switch (esc)
527+
{
528+
case '\\':
529+
quoted.append('\\');
530+
break;
531+
case '"':
532+
quoted.append('"');
533+
break;
534+
default:
535+
// unknown escape - preserve the backslash and the character (e.g., file paths like \t)
536+
quoted.append('\\');
537+
quoted.append(esc);
538+
break;
539+
}
540+
continue;
541+
}
542+
if (qc == '"')
543+
break; // found closing quote
544+
quoted.append(qc);
545+
}
546+
547+
tokens.add(new TokenTypeAssociation(quoted.toString(), TokenType.LITERAL_EXPRESSION));
548+
// continue to next character
549+
continue;
550+
}
551+
552+
// Normal processing: append char and continue token detection
553+
writer.write(ch);
495554
final String checkForTokenString = writer.toString();
496555

497556
// check to see if we have an exact match to a token
498557
TokenType exactMatchToken = tokenMap.get(checkForTokenString);
499558

500559
if (exactMatchToken != null)
501560
{
502-
// if the token is an operator, we need to keep looking forward to the next
561+
// if the token is an operator or certificate ref, we need to keep looking forward to the next
503562
// character because some operators are made up of the exact same characters.. we
504563
// may have a partial string of an operator with more characters
505564
if (exactMatchToken == TokenType.OPERATOR_EXPRESSION || exactMatchToken == TokenType.CERTIFICATE_REFERENCE_EXPRESSION)
@@ -535,8 +594,8 @@ protected Vector<TokenTypeAssociation> parseToTokens(InputStream stream) throws
535594

536595
exactMatchToken = tokenMap.get(nextToken);
537596
if (exactMatchToken != null)
538-
{
539-
597+
{
598+
540599
tokens.add(new TokenTypeAssociation(nextToken, exactMatchToken));
541600
}
542601
else
@@ -549,6 +608,7 @@ protected Vector<TokenTypeAssociation> parseToTokens(InputStream stream) throws
549608
{
550609
// we didn't hit an exact match, but the new character we hit may be a reserved token
551610
// check to see if the checkForTokenString now contains a reserved token
611+
boolean handled = false;
552612
for (String key : tokenMap.keySet())
553613
{
554614
int idx = checkForTokenString.indexOf(key);
@@ -581,13 +641,19 @@ protected Vector<TokenTypeAssociation> parseToTokens(InputStream stream) throws
581641
// the token is not an operator, so add it the token vector
582642
tokens.add(new TokenTypeAssociation(secondToken, exactMatchToken));
583643
}
644+
handled = true;
584645
break;
585646
}
586647
}
648+
649+
if (!handled)
650+
{
651+
// nothing special found; continue accumulating
652+
}
587653
}
588654
}
589-
}
590-
655+
}
656+
591657
// now that we have completed traversing the expression lexicon, if there is anything left over in the writer then
592658
// add it as a token
593659
final String remainingString = writer.toString().trim();
@@ -638,7 +704,13 @@ protected static enum TokenType
638704
/**
639705
* A certificate reference expression
640706
*/
641-
CERTIFICATE_REFERENCE_EXPRESSION;
707+
CERTIFICATE_REFERENCE_EXPRESSION,
708+
709+
/**
710+
* Marks the beginning or end of LITERAL_EXPRESSION where all contents regardless of character will
711+
* be considered part of the LIBERAL_EXPRESSION.
712+
*/
713+
LITERAL_QUOTE;
642714
}
643715

644716
protected Integer resetLevel()

src/test/java/org/nhindirect/policy/impl/SimpleTextV1LexiconPolicyParser_parseToTokensTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,18 @@ public void testParse_requiredCertField_validateTokens() throws Exception
7575

7676
stream.close();
7777
}
78+
79+
@Test
80+
public void testParse_regExWithParenthsis_validateTokens() throws Exception
81+
{
82+
final SimpleTextV1LexiconPolicyParser parser = new SimpleTextV1LexiconPolicyParser();
83+
final InputStream stream = FileUtils.openInputStream(new File("./src/test/resources/policies/simpleLexiconWithRegEx.txt"));
84+
85+
Vector<SimpleTextV1LexiconPolicyParser.TokenTypeAssociation> tokens = parser.parseToTokens(stream);
86+
assertEquals(3, tokens.size());
87+
88+
stream.close();
89+
}
90+
91+
7892
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.nhindirect.policy.impl;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.io.InputStream;
6+
import java.nio.charset.Charset;
7+
8+
import org.apache.commons.io.IOUtils;
9+
import org.junit.jupiter.api.Test;
10+
11+
public class SimpleTextV1LexiconPolicyParser_quotedEscapesTest
12+
{
13+
@Test
14+
public void testQuotedLiteral_containsParenthesesAndOperators_isSingleLiteral() throws Exception
15+
{
16+
final SimpleTextV1LexiconPolicyParser parser = new SimpleTextV1LexiconPolicyParser();
17+
final InputStream stream = IOUtils.toInputStream("\"(this && that)\"", Charset.defaultCharset());
18+
19+
final java.util.Vector<SimpleTextV1LexiconPolicyParser.TokenTypeAssociation> tokens = parser.parseToTokens(stream);
20+
assertEquals(1, tokens.size());
21+
assertEquals(SimpleTextV1LexiconPolicyParser.TokenType.LITERAL_EXPRESSION, tokens.get(0).getType());
22+
assertEquals("(this && that)", tokens.get(0).getToken());
23+
24+
stream.close();
25+
}
26+
27+
@Test
28+
public void testQuotedLiteral_escapedQuote_insideLiteral() throws Exception
29+
{
30+
final SimpleTextV1LexiconPolicyParser parser = new SimpleTextV1LexiconPolicyParser();
31+
final InputStream stream = IOUtils.toInputStream("\"He said \\\"Hello\\\" to me\"", Charset.defaultCharset());
32+
33+
final java.util.Vector<SimpleTextV1LexiconPolicyParser.TokenTypeAssociation> tokens = parser.parseToTokens(stream);
34+
assertEquals(1, tokens.size());
35+
assertEquals("He said \"Hello\" to me", tokens.get(0).getToken());
36+
37+
stream.close();
38+
}
39+
40+
@Test
41+
public void testQuotedLiteral_escapedBackslash_insideLiteral() throws Exception
42+
{
43+
final SimpleTextV1LexiconPolicyParser parser = new SimpleTextV1LexiconPolicyParser();
44+
final InputStream stream = IOUtils.toInputStream("\"C:\\\\path\\to\\file\"", Charset.defaultCharset());
45+
46+
final java.util.Vector<SimpleTextV1LexiconPolicyParser.TokenTypeAssociation> tokens = parser.parseToTokens(stream);
47+
assertEquals(1, tokens.size());
48+
assertEquals("C:\\path\\to\\file", tokens.get(0).getToken());
49+
50+
stream.close();
51+
}
52+
}
53+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
X509.TBS.EXTENSION.CertificatePolicies.PolicyOIDs {?} "^1\\.3\\.6\\.1\\.4\\.1\\.41179\\.2\\.1(\\.[0-9]+)*$"

0 commit comments

Comments
 (0)