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  
34          String coords1;
35          String coords2;
36  
37          if (this.length1 == 0) {
38              coords1 = this.start1 + ",0";
39          } else if (this.length1 == 1) {
40              coords1 = Integer.toString(this.start1 + 1);
41          } else {
42              coords1 = (this.start1 + 1) + "," + this.length1;
43          }
44  
45          if (this.length2 == 0) {
46              coords2 = this.start2 + ",0";
47          } else if (this.length2 == 1) {
48              coords2 = Integer.toString(this.start2 + 1);
49          } else {
50              coords2 = (this.start2 + 1) + "," + this.length2;
51          }
52  
53          StringBuilder text = new StringBuilder();
54          text.append("@@ -").append(coords1).append(" +").append(coords2)
55          .append(" @@\n");
56  
57          // Escape the body of the patch with %xx notation.
58          for (Diff aDiff : this.diffs) {
59              switch (aDiff.getOperation()) {
60              case INSERT:
61                  text.append('+');
62                  break;
63              case DELETE:
64                  text.append('-');
65                  break;
66              case EQUAL:
67                  text.append(' ');
68                  break;
69              }
70              text.append(URLEncoder.encode(aDiff.getText(), StandardCharsets.UTF_8).replace('+', ' '))
71              .append("\n");
72          }
73  
74          return Patch.unescapeForEncodeUriCompatability(text.toString());
75      }
76      
77      /**
78       * Unescape selected chars for compatibility with JavaScript's encodeURI.
79       * In speed critical applications this could be dropped since the
80       * receiving application will certainly decode these fine.
81       * Note that this function is case-sensitive. Thus, "%3f" would not be
82       * unescaped.  But this is ok because it is only called with the output of
83       * URLEncoder.encode() which returns uppercase hex.
84       *
85       * Example: "%3F" -> "?", "%24" -> "$", etc.
86       *
87       * @param str The string to escape.
88       * @return The escaped string.
89       */
90      public static String unescapeForEncodeUriCompatability(String str) {
91          return str.replace("%21", "!").replace("%7E", "~")
92              .replace("%27", "'").replace("%28", "(").replace("%29", ")")
93              .replace("%3B", ";").replace("%2F", "/").replace("%3F", "?")
94              .replace("%3A", ":").replace("%40", "@").replace("%26", "&")
95              .replace("%3D", "=").replace("%2B", "+").replace("%24", "$")
96              .replace("%2C", ",").replace("%23", "#");
97      }
98      
99      // Getter and setter
100 
101     public LinkedList<Diff> getDiffs() {
102         return this.diffs;
103     }
104 
105     public int getStart1() {
106         return this.start1;
107     }
108 
109     public void setStart1(int start1) {
110         this.start1 = start1;
111     }
112 
113     public int getStart2() {
114         return this.start2;
115     }
116 
117     public void setStart2(int start2) {
118         this.start2 = start2;
119     }
120 
121     public int getLength1() {
122         return this.length1;
123     }
124 
125     public void setLength1(int length1) {
126         this.length1 = length1;
127     }
128 
129     public int getLength2() {
130         return this.length2;
131     }
132 
133     public int setLength2(int length2) {
134         this.length2 = length2;
135         return length2;
136     }
137 }