View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
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.
14   */
15  
16  package org.fourthline.cling.model.message.header;
17  
18  import org.fourthline.cling.model.ServerClientTokens;
19  
20  /**
21   * @author Christian Bauer
22   */
23  public class ServerHeader extends UpnpHeader<ServerClientTokens> {
24  
25      public ServerHeader() {
26          setValue(new ServerClientTokens());
27      }
28  
29      public ServerHeader(ServerClientTokens tokens) {
30          setValue(tokens);
31      }
32  
33      public void setString(String s) throws InvalidHeaderException {
34          // TODO: This parsing is not as robust as I'd like, probably should use regexs instead
35  
36          // UDA 1.1/1.0 section 1.2.2 and RfC 2616, section 14.38
37          // OSNAME/OSVERSION UPnP/1.x PRODUCTNAME/PRODUCTVERSION
38          ServerClientTokens serverClientTokens = new ServerClientTokens();
39  
40          // They are all UNKNOWN at this point
41          serverClientTokens.setOsName(ServerClientTokens.UNKNOWN_PLACEHOLDER);
42          serverClientTokens.setOsVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER);
43          serverClientTokens.setProductName(ServerClientTokens.UNKNOWN_PLACEHOLDER);
44          serverClientTokens.setProductVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER);
45  
46          // We definitely need a UPnP product token
47          if (s.contains("UPnP/1.1")) {
48              serverClientTokens.setMinorVersion(1);
49          } else if (!s.contains("UPnP/1.")) {
50              throw new InvalidHeaderException("Missing 'UPnP/1.' in server information: " + s);
51          }
52  
53          // We might be lucky and the vendor has implemented other tokens correctly. so let's at least try
54          try {
55  
56              int numberOfSpaces = 0;
57              for( int i = 0; i < s.length(); i++ ) {
58                  if( s.charAt(i) == ' ' ) numberOfSpaces++;
59              }
60  
61              String[] osNameVersion;
62              String[] productNameVersion;
63  
64              if (s.contains(",")) {
65  
66                  // Some guys think that the tokens are separated with commas, not whitespace (read section 3.8 of the HTTP spec!)
67                  String[] productTokens = s.split(",");
68                  osNameVersion = productTokens[0].split("/");
69                  productNameVersion = productTokens[2].split("/");
70  
71              } else if (numberOfSpaces > 2) {
72  
73                  // Some guys think that whitespace in token names is OK... it's not ... but let's try...
74                  String beforeUpnpToken = s.substring(0, s.indexOf("UPnP/1.")).trim();
75                  String afterUpnpToken = s.substring(s.indexOf("UPnP/1.")+8).trim(); // Assumes minor version is 0-9!
76                  osNameVersion = beforeUpnpToken.split("/");
77                  productNameVersion = afterUpnpToken.split("/");
78  
79              } else {
80  
81                  // Finally, how it is supposed to be, according to UPnP UDA 1.1 (not 1.0 and not HTTP spec!)
82                  String[] productTokens = s.split(" ");
83                  osNameVersion = productTokens[0].split("/");
84                  productNameVersion = productTokens[2].split("/");
85              }
86  
87  
88              serverClientTokens.setOsName(osNameVersion[0].trim());
89              if (osNameVersion.length > 1) {
90                  serverClientTokens.setOsVersion(osNameVersion[1].trim());
91              }
92              serverClientTokens.setProductName(productNameVersion[0].trim());
93              if (productNameVersion.length > 1) {
94                  serverClientTokens.setProductVersion(productNameVersion[1].trim());
95              }
96  
97          } catch (Exception ex) {
98  
99              // If something goes wrong, go back to defaults
100             serverClientTokens.setOsName(ServerClientTokens.UNKNOWN_PLACEHOLDER);
101             serverClientTokens.setOsVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER);
102             serverClientTokens.setProductName(ServerClientTokens.UNKNOWN_PLACEHOLDER);
103             serverClientTokens.setProductVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER);
104 
105 
106             /* These are the rules:
107 
108               Many HTTP/1.1 header field values consist of words separated by LWS or special characters. These special
109               characters MUST be in a quoted string to be used within a parameter value (as defined in section 3.6).
110 
111                token          = 1*<any CHAR except CTLs or separators>
112                separators     = "(" | ")" | "<" | ">" | "@"
113                               | "," | ";" | ":" | "\" | <">
114                               | "/" | "[" | "]" | "?" | "="
115                               | "{" | "}" | SP | HT
116              */
117         }
118 
119         setValue(serverClientTokens);
120     }
121 
122     public String getString() {
123         return getValue().getHttpToken();
124     }
125 }