View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  
21  package org.apache.james.jspf.core;
22  
23  import org.apache.james.jspf.core.exceptions.PermErrorException;
24  
25  import java.util.HashMap;
26  import java.util.Map;
27  import java.util.Stack;
28  
29  /**
30   * 
31   * This Class is used as a container between the other classes. All necessary
32   * values get stored here and get retrieved from here.
33   * 
34   */
35  
36  public class SPFSession implements MacroData {
37  
38      private String ipAddress = ""; // also used for (i)<sending-host>
39  
40      private String mailFrom = ""; // (s)<responsible-sender>
41  
42      private String hostName = ""; // (h)<sender-domain>
43  
44      private String currentSenderPart = ""; // (l)
45  
46      private String currentDomain = ""; // (d)<current-domain>
47  
48      private String inAddress = "in-addr"; // (v)
49  
50      private String clientDomain = null; // (p)
51  
52      private String senderDomain = ""; // (o)
53  
54      private String readableIP = null; // (c)
55  
56      private String receivingDomain = null; // (r)
57  
58      private int currentDepth = 0;
59  
60      /**
61       * The maximum mechanismn which are allowed to use
62       */
63      public static final int MAX_DEPTH = 10;
64  
65      private String explanation = null;
66  
67      private String currentResult = null;
68  
69      private boolean ignoreExplanation = false;
70      
71      private Map attributes = new HashMap();
72      
73      private Stack checkers = new Stack();
74      
75      private String currentResultExpanded;
76      
77      /**
78       * Build the SPFSession from the given parameters
79       * 
80       * @param mailFrom
81       *            The emailaddress of the sender
82       * @param heloDomain
83       *            The helo provided by the sender
84       * @param clientIP
85       *            The ipaddress of the client
86       * 
87       */
88      public SPFSession(String mailFrom, String heloDomain, String clientIP) {
89          super();
90          this.mailFrom = mailFrom.trim();
91          this.hostName = heloDomain.trim();
92         
93          try {
94              this.ipAddress = IPAddr.getProperIpAddress(clientIP.trim());
95              // get the in Address
96              this.inAddress = IPAddr.getInAddress(clientIP);
97          } catch (PermErrorException e) {
98              // ip was not rfc conform
99              this.setCurrentResultExpanded(e.getResult());
100         }
101 
102         // if nullsender is used postmaster@helo will be used as email
103         if (mailFrom.equals("")) {
104             this.currentSenderPart = "postmaster";
105             this.senderDomain = hostName;
106             this.mailFrom = currentSenderPart + "@" + hostName;
107         } else {
108             String[] fromParts = mailFrom.split("@");
109             // What to do when mailFrom is "@example.com" ?
110             if (fromParts.length > 1) {
111                 this.senderDomain = fromParts[fromParts.length -1];
112                 this.currentSenderPart = mailFrom.substring(0, mailFrom.length() - senderDomain.length() - 1);
113                 if (this.currentSenderPart.length() == 0) {
114                     this.currentSenderPart = "postmaster";
115                 }
116             } else {
117                 this.currentSenderPart = "postmaster";
118                 this.senderDomain = mailFrom;
119             }
120         }
121         this.currentDomain = this.senderDomain;
122     }
123 
124     /**
125      * @see org.apache.james.jspf.core.MacroData#getCurrentSenderPart()
126      */
127     public String getCurrentSenderPart() {
128         return currentSenderPart;
129     }
130 
131     /**
132      * @see org.apache.james.jspf.core.MacroData#getMailFrom()
133      */
134     public String getMailFrom() {
135         return mailFrom;
136     }
137 
138     /**
139      * @see org.apache.james.jspf.core.MacroData#getHostName()
140      */
141     public String getHostName() {
142         return hostName;
143     }
144 
145     /**
146      * @see org.apache.james.jspf.core.MacroData#getCurrentDomain()
147      */
148     public String getCurrentDomain() {
149         return currentDomain;
150     }
151 
152     /**
153      * @see org.apache.james.jspf.core.MacroData#getInAddress()
154      */
155     public String getInAddress() {
156         return inAddress;
157     }
158 
159     /**
160      * @see org.apache.james.jspf.core.MacroData#getClientDomain()
161      */
162     public String getClientDomain() {
163         return clientDomain;
164     }
165     
166     /**
167      * Sets the calculated clientDomain
168      * @param clientDomain the new clientDomain
169      */
170     public void setClientDomain(String clientDomain) {
171         this.clientDomain = clientDomain;
172     }
173 
174     /**
175      * @see org.apache.james.jspf.core.MacroData#getSenderDomain()
176      */
177     public String getSenderDomain() {
178         return senderDomain;
179     }
180 
181     /**
182      * Get the ipAddress which was used to connect
183      * 
184      * @return ipAddres 
185      */
186     public String getIpAddress() {
187         return ipAddress;
188     }
189     
190     /**
191      * @see org.apache.james.jspf.core.MacroData#getMacroIpAddress()
192      */
193     public String getMacroIpAddress() {
194         
195         if (IPAddr.isIPV6(ipAddress)) {
196             try {
197                 return IPAddr.getAddress(ipAddress).getNibbleFormat();
198             } catch (PermErrorException e) {
199             }
200         } 
201         
202         return ipAddress;
203 
204     }
205 
206     /**
207      * @see org.apache.james.jspf.core.MacroData#getTimeStamp()
208      */
209     public long getTimeStamp() {
210         return System.currentTimeMillis();
211     }
212 
213     /**
214      * @see org.apache.james.jspf.core.MacroData#getReadableIP()
215      */
216     public String getReadableIP() {
217         if (readableIP == null) {
218             readableIP = IPAddr.getReadableIP(ipAddress);
219         }
220         return readableIP;
221     }
222 
223     /**
224      * @see org.apache.james.jspf.core.MacroData#getReceivingDomain()
225      */
226     public String getReceivingDomain() {
227         return receivingDomain;
228     }
229     
230     /**
231      * Sets the new receiving domain
232      * 
233      * @param receivingDomain the new receiving domain
234      */
235     public void setReceivingDomain(String receivingDomain) {
236         this.receivingDomain = receivingDomain;
237     }
238     
239     /**
240      * Increase the current depth:
241      * 
242      * if we reach maximum calls we must throw a PermErrorException. See
243      * SPF-RFC Section 10.1. Processing Limits
244      */
245     public void increaseCurrentDepth() throws PermErrorException {
246         this.currentDepth++;
247         if (currentDepth > MAX_DEPTH)
248             throw new PermErrorException(
249                     "Maximum mechanism/modifiers calls done: "
250                         + currentDepth);
251     }
252 
253     /**
254      * Set the currentDomain
255      * 
256      * @param domain The current used domain
257      */
258     public void setCurrentDomain(String domain) {
259         this.currentDomain = domain;
260     }
261 
262     /**
263      * Set the explanation which will returned when a fail match
264      * 
265      * @param explanation
266      *            This String is set as explanation
267      */
268     public void setExplanation(String explanation) {
269         this.explanation = explanation;
270     }
271 
272     /**
273      * Get the explanation
274      * 
275      * @return explanation
276      */
277     public String getExplanation() {
278         return explanation;
279     }
280 
281     /**
282      * Set the current result
283      * 
284      * @param result
285      *            result
286      */
287     public void setCurrentResult(String result) {
288         this.currentResult = result;
289     }
290 
291     /**
292      * Get the current result
293      * 
294      * @return current result
295      */
296     public String getCurrentResult() {
297         return currentResult;
298     }
299     
300     /**
301      * Get set to true if the explanation should be ignored
302      * 
303      * @param ignoreExplanation true or false
304      */
305     public void setIgnoreExplanation(boolean ignoreExplanation) {
306         this.ignoreExplanation = ignoreExplanation; 
307     }
308     
309     /**
310      * Return true if the explanation should be ignored
311      * 
312      * @return true of false
313      */
314     public boolean ignoreExplanation() {
315         return ignoreExplanation;
316     }
317     
318     /**
319      * Retrieve a stored attribute
320      * 
321      * @param key the attribute key
322      * @return the stored attribute
323      */
324     public Object getAttribute(String key) {
325         return attributes.get(key);
326     }
327     
328     /**
329      * Sets a new attribute in the session
330      * 
331      * @param key attribute key
332      * @param value the value for this attribute
333      */
334     public void setAttribute(String key, Object value) {
335         this.attributes.put(key, value);
336     }
337     
338     /**
339      * Remove the attribute stored under the given key
340      * 
341      * @param key the key of the attribute
342      * @return object the attribute which was stored with the key
343      */
344     public Object removeAttribute(String key) {
345         return this.attributes.remove(key);
346     }
347 
348     /**
349      * Add the given SPFChecker on top of the stack
350      * 
351      * @param checker  
352      */
353     public void pushChecker(SPFChecker checker) {
354         checkers.push(checker);
355     }
356     
357     /**
358      * Remove the SPFChecker on the top and return it. If no SPFChecker is left
359      * null is returned
360      * 
361      * @return the last checker
362      */
363     public SPFChecker popChecker() {
364         if (checkers.isEmpty()) {
365             return null;
366         } else {
367             SPFChecker checker = (SPFChecker) checkers.pop();
368             return checker;
369         }
370     }
371 
372     /**
373      * @param result
374      */
375     public void setCurrentResultExpanded(String result) {
376         this.currentResultExpanded = result;
377     }
378 
379     /**
380      * @return current result converted/expanded
381      */
382     public String getCurrentResultExpanded() {
383         return currentResultExpanded;
384     }
385 
386 }