View Javadoc
1   package com.jsql.model.injection.strategy.blind.patch;
2   
3   import java.net.URLEncoder;
4   import java.nio.charset.StandardCharsets;
5   import java.util.LinkedList;
6   
7   /**
8    * Class representing one patch operation.
9    */
10  public class Patch {
11  
12      private final LinkedList<Diff> diffs;
13      private int start1;
14      private int start2;
15      private int length1;
16      private int length2;
17  
18      /**
19       * Constructor.  Initializes with an empty list of diffs.
20       */
21      public Patch() {
22          this.diffs = new LinkedList<>();
23      }
24  
25      /**
26       * Emmulate GNU diff's format.
27       * Header: @@ -382,8 +481,9 @@
28       * Indicies are printed as 1-based, not 0-based.
29       * @return The GNU diff string.
30       */
31      @Override
32      public String toString() {
33          String coords1;
34          String coords2;
35  
36          if (this.length1 == 0) {
37              coords1 = this.start1 + ",0";
38          } else if (this.length1 == 1) {
39              coords1 = Integer.toString(this.start1 + 1);
40          } else {
41              coords1 = (this.start1 + 1) + "," + this.length1;
42          }
43  
44          if (this.length2 == 0) {
45              coords2 = this.start2 + ",0";
46          } else if (this.length2 == 1) {
47              coords2 = Integer.toString(this.start2 + 1);
48          } else {
49              coords2 = (this.start2 + 1) + "," + this.length2;
50          }
51  
52          StringBuilder text = new StringBuilder();
53          text.append("@@ -").append(coords1).append(" +").append(coords2)
54                  .append(" @@\n");
55  
56          // Escape the body of the patch with %xx notation.
57          for (Diff aDiff : this.diffs) {
58              switch (aDiff.getOperation()) {
59                  case INSERT:
60                      text.append('+');
61                      break;
62                  case DELETE:
63                      text.append('-');
64                      break;
65                  case EQUAL:
66                      text.append(' ');
67                      break;
68              }
69              text.append(URLEncoder.encode(aDiff.getText(), StandardCharsets.UTF_8).replace('+', ' '))
70                      .append("\n");
71          }
72  
73          return Patch.unescapeForEncodeUriCompatability(text.toString());
74      }
75  
76      /**
77       * Unescape selected chars for compatibility with JavaScript's encodeURI.
78       * In speed critical applications this could be dropped since the
79       * receiving application will certainly decode these fine.
80       * Note that this function is case-sensitive. Thus, "%3f" would not be
81       * unescaped.  But this is ok because it is only called with the output of
82       * URLEncoder.encode() which returns uppercase hex.
83       *
84       * Example: "%3F" -> "?", "%24" -> "$", etc.
85       *
86       * @param str The string to escape.
87       * @return The escaped string.
88       */
89      public static String unescapeForEncodeUriCompatability(String str) {
90          return str.replace("%21", "!").replace("%7E", "~")
91                  .replace("%27", "'").replace("%28", "(").replace("%29", ")")
92                  .replace("%3B", ";").replace("%2F", "/").replace("%3F", "?")
93                  .replace("%3A", ":").replace("%40", "@").replace("%26", "&")
94                  .replace("%3D", "=").replace("%2B", "+").replace("%24", "$")
95                  .replace("%2C", ",").replace("%23", "#");
96      }
97  
98      // Getter and setter
99  
100     public LinkedList<Diff> getDiffs() {
101         return this.diffs;
102     }
103 
104     public int getStart1() {
105         return this.start1;
106     }
107 
108     public void setStart1(int start1) {
109         this.start1 = start1;
110     }
111 
112     public int getStart2() {
113         return this.start2;
114     }
115 
116     public void setStart2(int start2) {
117         this.start2 = start2;
118     }
119 
120     public int getLength1() {
121         return this.length1;
122     }
123 
124     public void setLength1(int length1) {
125         this.length1 = length1;
126     }
127 
128     public int getLength2() {
129         return this.length2;
130     }
131 
132     public int setLength2(int length2) {
133         this.length2 = length2;
134         return length2;
135     }
136 }