1 /*
2  * Paros and its related class files.
3  *
4  * Paros is an HTTP/HTTPS proxy for assessing web application security.
5  * Copyright (C) 2003-2004 Chinotec Technologies Company
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the Clarified Artistic License
9  * as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * Clarified Artistic License for more details.
15  *
16  * You should have received a copy of the Clarified Artistic License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  */
20 // ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments
21 // ZAP: 2013/07/02 Changed API to public because future extensible Variant model
22 // ZAP: 2014/01/06 Issue 965: Support 'single page' apps and 'non standard' parameter separators
23 // ZAP: 2014/02/08 Used the same constants used in ScanParam Target settings
24 // ZAP: 2016/02/22 Add hashCode, equals and toString methods. Remove redundant instance variable
25 // initialisations.
26 // ZAP: 2018/01/03 Added type constants for revised multipart/form-data handling
27 // ZAP: 2018/02/19 Added type constants for application/json handling
28 // ZAP: 2019/06/01 Normalise line endings.
29 // ZAP: 2019/06/05 Normalise format/style.
30 // ZAP: 2020/09/01 Added compareTo method.
31 // ZAP: 2020/09/22 Added type constant for GraphQL Inline Arguments handling.
32 package org.parosproxy.paros.core.scanner;
33 
34 public class NameValuePair implements Comparable<NameValuePair> {
35 
36     // NOTE: After adding a new type update ScannerParamFilter.
37     public static final int TYPE_URL_PATH = ScannerParam.TARGET_URLPATH;
38     public static final int TYPE_QUERY_STRING = ScannerParam.TARGET_QUERYSTRING;
39     public static final int TYPE_COOKIE = ScannerParam.TARGET_COOKIE;
40     public static final int TYPE_HEADER = ScannerParam.TARGET_HTTPHEADERS;
41     public static final int TYPE_POST_DATA = ScannerParam.TARGET_POSTDATA;
42     /**
43      * A "normal" (non-file) multipart/form-data parameter
44      *
45      * @since 2.8.0
46      */
47     public static final int TYPE_MULTIPART_DATA_PARAM = 33;
48     /**
49      * A file (content) multipart/form-data file parameter
50      *
51      * @since 2.8.0
52      */
53     public static final int TYPE_MULTIPART_DATA_FILE_PARAM = 34;
54     /**
55      * The filename portion of a multipart/form-data file parameter
56      *
57      * @since 2.8.0
58      */
59     public static final int TYPE_MULTIPART_DATA_FILE_NAME = 35;
60     /**
61      * The content-type portion of a multipart/form-data file parameter
62      *
63      * @since 2.8.0
64      */
65     public static final int TYPE_MULTIPART_DATA_FILE_CONTENTTYPE = 36;
66     /**
67      * The application/json content-type of a web application
68      *
69      * @since 2.8.0
70      */
71     public static final int TYPE_JSON = 37;
72     /**
73      * The inline arguments in a GraphQL query
74      *
75      * @since 2.10.0
76      */
77     public static final int TYPE_GRAPHQL_INLINE = 38;
78 
79     public static final int TYPE_UNDEFINED = -1;
80 
81     private final int targetType;
82     private String name;
83     private String value;
84     private int position;
85 
86     /**
87      * @param name
88      * @param value
89      */
NameValuePair(int type, String name, String value, int position)90     public NameValuePair(int type, String name, String value, int position) {
91         super();
92         this.targetType = type;
93         this.name = name;
94         this.value = value;
95         this.position = position;
96     }
97 
98     /**
99      * Returns the type
100      *
101      * @return
102      */
getType()103     public int getType() {
104         return targetType;
105     }
106 
107     /** @return Returns the name. */
getName()108     public String getName() {
109         return name;
110     }
111 
112     /** @param name The name to set. */
setName(String name)113     public void setName(String name) {
114         this.name = name;
115     }
116 
117     /** @return Returns the value. */
getValue()118     public String getValue() {
119         return value;
120     }
121 
122     /** @param value The value to set. */
setValue(String value)123     public void setValue(String value) {
124         this.value = value;
125     }
126 
127     /** @return Returns the position. */
getPosition()128     public int getPosition() {
129         return position;
130     }
131 
132     /** @param position The position to set. */
setPosition(int position)133     public void setPosition(int position) {
134         this.position = position;
135     }
136 
137     @Override
hashCode()138     public int hashCode() {
139         final int prime = 31;
140         int result = 1;
141         result = prime * result + ((name == null) ? 0 : name.hashCode());
142         result = prime * result + position;
143         result = prime * result + targetType;
144         result = prime * result + ((value == null) ? 0 : value.hashCode());
145         return result;
146     }
147 
148     @Override
equals(Object obj)149     public boolean equals(Object obj) {
150         if (this == obj) {
151             return true;
152         }
153         if (obj == null) {
154             return false;
155         }
156         if (getClass() != obj.getClass()) {
157             return false;
158         }
159         NameValuePair other = (NameValuePair) obj;
160         if (name == null) {
161             if (other.name != null) {
162                 return false;
163             }
164         } else if (!name.equals(other.name)) {
165             return false;
166         }
167         if (position != other.position) {
168             return false;
169         }
170         if (targetType != other.targetType) {
171             return false;
172         }
173         if (value == null) {
174             if (other.value != null) {
175                 return false;
176             }
177         } else if (!value.equals(other.value)) {
178             return false;
179         }
180         return true;
181     }
182 
183     @Override
toString()184     public String toString() {
185         StringBuilder strBuilder = new StringBuilder(75);
186         strBuilder.append("[Position=").append(position);
187         strBuilder.append(", Type=").append(targetType);
188         if (name != null) {
189             strBuilder.append(", Name=").append(name);
190         }
191         if (value != null) {
192             strBuilder.append(", Value=").append(value);
193         }
194         strBuilder.append(']');
195         return strBuilder.toString();
196     }
197 
198     @Override
compareTo(NameValuePair nvp)199     public int compareTo(NameValuePair nvp) {
200         if (nvp == null) {
201             return -1;
202         }
203         if (nvp.targetType != targetType) {
204             return nvp.targetType - targetType;
205         }
206         if (nvp.position != position) {
207             return nvp.position - position;
208         }
209         int cmp;
210         if (nvp.name != null && name != null) {
211             cmp = nvp.name.compareTo(name);
212             if (cmp != 0) {
213                 return cmp;
214             }
215         } else if (nvp.name == null || name == null) {
216             // They can't both be null due to previous test
217             return nvp.name != null ? -1 : 1;
218         }
219         if (nvp.value != null && value != null) {
220             cmp = nvp.value.compareTo(value);
221             if (cmp != 0) {
222                 return cmp;
223             }
224         } else if (nvp.value == null || value == null) {
225             return nvp.value != null ? -1 : 1;
226         }
227         return 0;
228     }
229 }
230