| %line | %branch | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| org.apache.commons.net.ftp.parser.UnixFTPEntryParser |
|
|
| 1 | /* |
|
| 2 | * Copyright 2001-2005 The Apache Software Foundation |
|
| 3 | * |
|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 5 | * you may not use this file except in compliance with the License. |
|
| 6 | * You may obtain a copy of the License at |
|
| 7 | * |
|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
| 9 | * |
|
| 10 | * Unless required by applicable law or agreed to in writing, software |
|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 13 | * See the License for the specific language governing permissions and |
|
| 14 | * limitations under the License. |
|
| 15 | */ |
|
| 16 | package org.apache.commons.net.ftp.parser; |
|
| 17 | import java.text.ParseException; |
|
| 18 | ||
| 19 | import org.apache.commons.net.ftp.FTPClientConfig; |
|
| 20 | import org.apache.commons.net.ftp.FTPFile; |
|
| 21 | ||
| 22 | /** |
|
| 23 | * Implementation FTPFileEntryParser and FTPFileListParser for standard |
|
| 24 | * Unix Systems. |
|
| 25 | * |
|
| 26 | * This class is based on the logic of Daniel Savarese's |
|
| 27 | * DefaultFTPListParser, but adapted to use regular expressions and to fit the |
|
| 28 | * new FTPFileEntryParser interface. |
|
| 29 | * @version $Id: UnixFTPEntryParser.java 161712 2005-04-18 02:57:04Z scohen $ |
|
| 30 | * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions) |
|
| 31 | */ |
|
| 32 | public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl |
|
| 33 | { |
|
| 34 | /** |
|
| 35 | * months abbreviations looked for by this parser. Also used |
|
| 36 | * to determine which month is matched by the parser |
|
| 37 | */ |
|
| 38 | private static final String DEFAULT_MONTHS = |
|
| 39 | "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"; |
|
| 40 | ||
| 41 | static final String DEFAULT_DATE_FORMAT |
|
| 42 | = "MMM d yyyy"; //Nov 9 2001 |
|
| 43 | ||
| 44 | static final String DEFAULT_RECENT_DATE_FORMAT |
|
| 45 | = "MMM d HH:mm"; //Nov 9 20:06 |
|
| 46 | ||
| 47 | static final String NUMERIC_DATE_FORMAT |
|
| 48 | = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06 |
|
| 49 | ||
| 50 | /** |
|
| 51 | * Some Linux distributions are now shipping an FTP server which formats |
|
| 52 | * file listing dates in an all-numeric format: |
|
| 53 | * <code>"yyyy-MM-dd HH:mm</code>. |
|
| 54 | * This is a very welcome development, and hopefully it will soon become |
|
| 55 | * the standard. However, since it is so new, for now, and possibly |
|
| 56 | * forever, we merely accomodate it, but do not make it the default. |
|
| 57 | * <p> |
|
| 58 | * For now end users may specify this format only via |
|
| 59 | * <code>UnixFTPEntryParser(FTPClientConfig)</code>. |
|
| 60 | * Steve Cohen - 2005-04-17 |
|
| 61 | */ |
|
| 62 | 10 | public static final FTPClientConfig NUMERIC_DATE_CONFIG = |
| 63 | new FTPClientConfig( |
|
| 64 | FTPClientConfig.SYST_UNIX, |
|
| 65 | NUMERIC_DATE_FORMAT, |
|
| 66 | null, class="keyword">null, class="keyword">null, class="keyword">null); |
|
| 67 | ||
| 68 | /** |
|
| 69 | * this is the regular expression used by this parser. |
|
| 70 | * |
|
| 71 | * Permissions: |
|
| 72 | * r the file is readable |
|
| 73 | * w the file is writable |
|
| 74 | * x the file is executable |
|
| 75 | * - the indicated permission is not granted |
|
| 76 | * L mandatory locking occurs during access (the set-group-ID bit is |
|
| 77 | * on and the group execution bit is off) |
|
| 78 | * s the set-user-ID or set-group-ID bit is on, and the corresponding |
|
| 79 | * user or group execution bit is also on |
|
| 80 | * S undefined bit-state (the set-user-ID bit is on and the user |
|
| 81 | * execution bit is off) |
|
| 82 | * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and |
|
| 83 | * execution is on |
|
| 84 | * T the 1000 bit is turned on, and execution is off (undefined bit- |
|
| 85 | * state) |
|
| 86 | */ |
|
| 87 | private static final String REGEX = |
|
| 88 | "([bcdlfmpSs-])" |
|
| 89 | +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+" |
|
| 90 | + "(\\d+)\\s+" |
|
| 91 | + "(\\S+)\\s+" |
|
| 92 | + "(?:(\\S+)\\s+)?" |
|
| 93 | + "(\\d+)\\s+" |
|
| 94 | ||
| 95 | /* |
|
| 96 | numeric or standard format date |
|
| 97 | */ |
|
| 98 | + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S+\\s+\\S+))\\s+" |
|
| 99 | ||
| 100 | /* |
|
| 101 | year (for non-recent standard format) |
|
| 102 | or time (for numeric or recent standard format |
|
| 103 | */ |
|
| 104 | + "(\\d+(?::\\d+)?)\\s+" |
|
| 105 | ||
| 106 | + "(\\S*)(\\s*.*)"; |
|
| 107 | ||
| 108 | ||
| 109 | /** |
|
| 110 | * The default constructor for a UnixFTPEntryParser object. |
|
| 111 | * |
|
| 112 | * @exception IllegalArgumentException |
|
| 113 | * Thrown if the regular expression is unparseable. Should not be seen |
|
| 114 | * under normal conditions. It it is seen, this is a sign that |
|
| 115 | * <code>REGEX</code> is not a valid regular expression. |
|
| 116 | */ |
|
| 117 | public UnixFTPEntryParser() |
|
| 118 | { |
|
| 119 | 92 | this(null); |
| 120 | 92 | } |
| 121 | ||
| 122 | /** |
|
| 123 | * This constructor allows the creation of a UnixFTPEntryParser object with |
|
| 124 | * something other than the default configuration. |
|
| 125 | * |
|
| 126 | * @param config The {@link FTPClientConfig configuration} object used to |
|
| 127 | * configure this parser. |
|
| 128 | * @exception IllegalArgumentException |
|
| 129 | * Thrown if the regular expression is unparseable. Should not be seen |
|
| 130 | * under normal conditions. It it is seen, this is a sign that |
|
| 131 | * <code>REGEX</code> is not a valid regular expression. |
|
| 132 | * @since 1.4 |
|
| 133 | */ |
|
| 134 | public UnixFTPEntryParser(FTPClientConfig config) |
|
| 135 | { |
|
| 136 | 94 | super(REGEX); |
| 137 | 94 | configure(config); |
| 138 | 94 | } |
| 139 | ||
| 140 | ||
| 141 | /** |
|
| 142 | * Parses a line of a unix (standard) FTP server file listing and converts |
|
| 143 | * it into a usable format in the form of an <code> FTPFile </code> |
|
| 144 | * instance. If the file listing line doesn't describe a file, |
|
| 145 | * <code> null </code> is returned, otherwise a <code> FTPFile </code> |
|
| 146 | * instance representing the files in the directory is returned. |
|
| 147 | * <p> |
|
| 148 | * @param entry A line of text from the file listing |
|
| 149 | * @return An FTPFile instance corresponding to the supplied entry |
|
| 150 | */ |
|
| 151 | public FTPFile parseFTPEntry(String entry) { |
|
| 152 | 154 | FTPFile file = new FTPFile(); |
| 153 | 154 | file.setRawListing(entry); |
| 154 | int type; |
|
| 155 | 154 | boolean isDevice = false; |
| 156 | ||
| 157 | 154 | if (matches(entry)) |
| 158 | { |
|
| 159 | 106 | String typeStr = group(1); |
| 160 | 106 | String hardLinkCount = group(15); |
| 161 | 106 | String usr = group(16); |
| 162 | 106 | String grp = group(17); |
| 163 | 106 | String filesize = group(18); |
| 164 | 106 | String datestr = group(19) + " " + group(20); |
| 165 | 106 | String name = group(21); |
| 166 | 106 | String endtoken = group(22); |
| 167 | ||
| 168 | try |
|
| 169 | { |
|
| 170 | 106 | file.setTimestamp(super.parseTimestamp(datestr)); |
| 171 | } |
|
| 172 | 18 | catch (ParseException e) |
| 173 | { |
|
| 174 | 18 | return null; // this is a parsing failure too. |
| 175 | 88 | } |
| 176 | ||
| 177 | ||
| 178 | // bcdlfmpSs- |
|
| 179 | 88 | switch (typeStr.charAt(0)) |
| 180 | { |
|
| 181 | case 'd': |
|
| 182 | 18 | type = FTPFile.DIRECTORY_TYPE; |
| 183 | 18 | break; |
| 184 | case 'l': |
|
| 185 | 8 | type = FTPFile.SYMBOLIC_LINK_TYPE; |
| 186 | 8 | break; |
| 187 | case 'b': |
|
| 188 | case 'c': |
|
| 189 | 4 | isDevice = true; |
| 190 | // break; - fall through |
|
| 191 | case 'f': |
|
| 192 | case '-': |
|
| 193 | 62 | type = FTPFile.FILE_TYPE; |
| 194 | 62 | break; |
| 195 | default: |
|
| 196 | 0 | type = FTPFile.UNKNOWN_TYPE; |
| 197 | } |
|
| 198 | ||
| 199 | 88 | file.setType(type); |
| 200 | ||
| 201 | 88 | int g = 4; |
| 202 | 352 | for (int access = 0; access < 3; access++, g += 4) |
| 203 | { |
|
| 204 | // Use != '-' to avoid having to check for suid and sticky bits |
|
| 205 | 264 | file.setPermission(access, FTPFile.READ_PERMISSION, |
| 206 | (!group(g).equals("-"))); |
|
| 207 | 264 | file.setPermission(access, FTPFile.WRITE_PERMISSION, |
| 208 | (!group(g + 1).equals("-"))); |
|
| 209 | ||
| 210 | 264 | String execPerm = group(g + 2); |
| 211 | 264 | if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0))) |
| 212 | { |
|
| 213 | 116 | file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true); |
| 214 | } |
|
| 215 | else |
|
| 216 | { |
|
| 217 | 148 | file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false); |
| 218 | } |
|
| 219 | } |
|
| 220 | ||
| 221 | 88 | if (!isDevice) |
| 222 | { |
|
| 223 | try |
|
| 224 | { |
|
| 225 | 84 | file.setHardLinkCount(Integer.parseInt(hardLinkCount)); |
| 226 | } |
|
| 227 | 0 | catch (NumberFormatException e) |
| 228 | { |
|
| 229 | // intentionally do nothing |
|
| 230 | 84 | } |
| 231 | } |
|
| 232 | ||
| 233 | 88 | file.setUser(usr); |
| 234 | 88 | file.setGroup(grp); |
| 235 | ||
| 236 | try |
|
| 237 | { |
|
| 238 | 88 | file.setSize(Long.parseLong(filesize)); |
| 239 | } |
|
| 240 | 0 | catch (NumberFormatException e) |
| 241 | { |
|
| 242 | // intentionally do nothing |
|
| 243 | 88 | } |
| 244 | ||
| 245 | 88 | if (null == endtoken) |
| 246 | { |
|
| 247 | 0 | file.setName(name); |
| 248 | } |
|
| 249 | else |
|
| 250 | { |
|
| 251 | // oddball cases like symbolic links, file names |
|
| 252 | // with spaces in them. |
|
| 253 | 88 | name += endtoken; |
| 254 | 88 | if (type == FTPFile.SYMBOLIC_LINK_TYPE) |
| 255 | { |
|
| 256 | ||
| 257 | 8 | int end = name.indexOf(" -> "); |
| 258 | // Give up if no link indicator is present |
|
| 259 | 8 | if (end == -1) |
| 260 | { |
|
| 261 | 4 | file.setName(name); |
| 262 | } |
|
| 263 | else |
|
| 264 | { |
|
| 265 | 4 | file.setName(name.substring(0, end)); |
| 266 | 4 | file.setLink(name.substring(end + 4)); |
| 267 | } |
|
| 268 | ||
| 269 | } |
|
| 270 | else |
|
| 271 | { |
|
| 272 | 80 | file.setName(name); |
| 273 | } |
|
| 274 | } |
|
| 275 | 88 | return file; |
| 276 | } |
|
| 277 | 48 | return null; |
| 278 | } |
|
| 279 | ||
| 280 | /** |
|
| 281 | * Defines a default configuration to be used when this class is |
|
| 282 | * instantiated without a {@link FTPClientConfig FTPClientConfig} |
|
| 283 | * parameter being specified. |
|
| 284 | * @return the default configuration for this parser. |
|
| 285 | */ |
|
| 286 | protected FTPClientConfig getDefaultConfiguration() { |
|
| 287 | 108 | return new FTPClientConfig( |
| 288 | FTPClientConfig.SYST_UNIX, |
|
| 289 | DEFAULT_DATE_FORMAT, |
|
| 290 | DEFAULT_RECENT_DATE_FORMAT, |
|
| 291 | null, class="keyword">null, class="keyword">null); |
|
| 292 | } |
|
| 293 | ||
| 294 | ||
| 295 | ||
| 296 | ||
| 297 | } |
| This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |