1:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60:
61: import ;
62: import ;
63: import ;
64: import ;
65:
66:
77: public class FTPConnection
78: {
79:
80:
83: public static final int FTP_PORT = 21;
84:
85:
88: public static final int FTP_DATA_PORT = 20;
89:
90:
91: protected static final String USER = "USER";
92: protected static final String PASS = "PASS";
93: protected static final String ACCT = "ACCT";
94: protected static final String CWD = "CWD";
95: protected static final String CDUP = "CDUP";
96: protected static final String SMNT = "SMNT";
97: protected static final String REIN = "REIN";
98: protected static final String QUIT = "QUIT";
99:
100: protected static final String PORT = "PORT";
101: protected static final String PASV = "PASV";
102: protected static final String TYPE = "TYPE";
103: protected static final String STRU = "STRU";
104: protected static final String MODE = "MODE";
105:
106: protected static final String RETR = "RETR";
107: protected static final String STOR = "STOR";
108: protected static final String STOU = "STOU";
109: protected static final String APPE = "APPE";
110: protected static final String ALLO = "ALLO";
111: protected static final String REST = "REST";
112: protected static final String RNFR = "RNFR";
113: protected static final String RNTO = "RNTO";
114: protected static final String ABOR = "ABOR";
115: protected static final String DELE = "DELE";
116: protected static final String RMD = "RMD";
117: protected static final String MKD = "MKD";
118: protected static final String PWD = "PWD";
119: protected static final String LIST = "LIST";
120: protected static final String NLST = "NLST";
121: protected static final String SITE = "SITE";
122: protected static final String SYST = "SYST";
123: protected static final String STAT = "STAT";
124: protected static final String HELP = "HELP";
125: protected static final String NOOP = "NOOP";
126:
127: protected static final String AUTH = "AUTH";
128: protected static final String PBSZ = "PBSZ";
129: protected static final String PROT = "PROT";
130: protected static final String CCC = "CCC";
131: protected static final String TLS = "TLS";
132:
133: public static final int TYPE_ASCII = 1;
134: public static final int TYPE_EBCDIC = 2;
135: public static final int TYPE_BINARY = 3;
136:
137: public static final int STRUCTURE_FILE = 1;
138: public static final int STRUCTURE_RECORD = 2;
139: public static final int STRUCTURE_PAGE = 3;
140:
141: public static final int MODE_STREAM = 1;
142: public static final int MODE_BLOCK = 2;
143: public static final int MODE_COMPRESSED = 3;
144:
145:
146: private static final String US_ASCII = "US-ASCII";
147:
148:
151: protected Socket socket;
152:
153:
156: protected LineInputStream in;
157:
158:
161: protected CRLFOutputStream out;
162:
163:
166: protected int connectionTimeout;
167:
168:
171: protected int timeout;
172:
173:
176: protected boolean debug;
177:
178:
181: protected DTP dtp;
182:
183:
186: protected int representationType = TYPE_ASCII;
187:
188:
191: protected int fileStructure = STRUCTURE_FILE;
192:
193:
196: protected int transferMode = MODE_STREAM;
197:
198:
201: protected boolean passive = false;
202:
203:
207: public FTPConnection(String hostname)
208: throws UnknownHostException, IOException
209: {
210: this(hostname, -1, 0, 0, false);
211: }
212:
213:
218: public FTPConnection(String hostname, int port)
219: throws UnknownHostException, IOException
220: {
221: this(hostname, port, 0, 0, false);
222: }
223:
224:
232: public FTPConnection(String hostname, int port,
233: int connectionTimeout, int timeout, boolean debug)
234: throws UnknownHostException, IOException
235: {
236: this.connectionTimeout = connectionTimeout;
237: this.timeout = timeout;
238: this.debug = debug;
239: if (port <= 0)
240: {
241: port = FTP_PORT;
242: }
243:
244:
245: socket = new Socket();
246: InetSocketAddress address = new InetSocketAddress(hostname, port);
247: if (connectionTimeout > 0)
248: {
249: socket.connect(address, connectionTimeout);
250: }
251: else
252: {
253: socket.connect(address);
254: }
255: if (timeout > 0)
256: {
257: socket.setSoTimeout(timeout);
258: }
259:
260: InputStream in = socket.getInputStream();
261: in = new BufferedInputStream(in);
262: in = new CRLFInputStream(in);
263: this.in = new LineInputStream(in);
264: OutputStream out = socket.getOutputStream();
265: out = new BufferedOutputStream(out);
266: this.out = new CRLFOutputStream(out);
267:
268:
269: FTPResponse response = getResponse();
270: switch (response.getCode())
271: {
272: case 220:
273: break;
274: default:
275: throw new FTPException(response);
276: }
277: }
278:
279:
287: public boolean authenticate(String username, String password)
288: throws IOException
289: {
290: String cmd = USER + ' ' + username;
291: send(cmd);
292: FTPResponse response = getResponse();
293: switch (response.getCode())
294: {
295: case 230:
296: return true;
297: case 331:
298: break;
299: case 332:
300: case 530:
301: return false;
302: default:
303: throw new FTPException(response);
304: }
305: cmd = PASS + ' ' + password;
306: send(cmd);
307: response = getResponse();
308: switch (response.getCode())
309: {
310: case 230:
311: case 202:
312: return true;
313: case 332:
314: case 530:
315: return false;
316: default:
317: throw new FTPException(response);
318: }
319: }
320:
321:
327: public boolean starttls(boolean confidential)
328: throws IOException
329: {
330: return starttls(confidential, new EmptyX509TrustManager());
331: }
332:
333:
340: public boolean starttls(boolean confidential, TrustManager tm)
341: throws IOException
342: {
343: try
344: {
345:
346:
347: SSLContext context = SSLContext.getInstance("TLS");
348:
349: TrustManager[] trust = new TrustManager[] { tm };
350: context.init(null, trust, null);
351: SSLSocketFactory factory = context.getSocketFactory();
352:
353: send(AUTH + ' ' + TLS);
354: FTPResponse response = getResponse();
355: switch (response.getCode())
356: {
357: case 500:
358: case 502:
359: case 504:
360: case 534:
361: case 431:
362: return false;
363: case 234:
364: break;
365: default:
366: throw new FTPException(response);
367: }
368:
369: String hostname = socket.getInetAddress().getHostName();
370: int port = socket.getPort();
371: SSLSocket ss =
372: (SSLSocket) factory.createSocket(socket, hostname, port, true);
373: String[] protocols = { "TLSv1", "SSLv3" };
374: ss.setEnabledProtocols(protocols);
375: ss.setUseClientMode(true);
376: ss.startHandshake();
377:
378:
379: send(PBSZ + ' ' + Integer.MAX_VALUE);
380: response = getResponse();
381: switch (response.getCode())
382: {
383: case 501:
384: case 503:
385: return false;
386: case 200:
387: break;
388: default:
389: throw new FTPException(response);
390: }
391: send(PROT + ' ' +(confidential ? 'P' : 'C'));
392: response = getResponse();
393: switch (response.getCode())
394: {
395: case 503:
396: case 504:
397: case 536:
398: return false;
399: case 200:
400: break;
401: default:
402: throw new FTPException(response);
403: }
404:
405: if (confidential)
406: {
407:
408: InputStream in = ss.getInputStream();
409: in = new BufferedInputStream(in);
410: in = new CRLFInputStream(in);
411: this.in = new LineInputStream(in);
412: OutputStream out = ss.getOutputStream();
413: out = new BufferedOutputStream(out);
414: this.out = new CRLFOutputStream(out);
415: }
416: return true;
417: }
418: catch (GeneralSecurityException e)
419: {
420: return false;
421: }
422: }
423:
424:
429: public boolean changeWorkingDirectory(String path)
430: throws IOException
431: {
432: String cmd = CWD + ' ' + path;
433: send(cmd);
434: FTPResponse response = getResponse();
435: switch (response.getCode())
436: {
437: case 250:
438: return true;
439: case 550:
440: return false;
441: default:
442: throw new FTPException(response);
443: }
444: }
445:
446:
450: public boolean changeToParentDirectory()
451: throws IOException
452: {
453: send(CDUP);
454: FTPResponse response = getResponse();
455: switch (response.getCode())
456: {
457: case 250:
458: return true;
459: case 550:
460: return false;
461: default:
462: throw new FTPException(response);
463: }
464: }
465:
466:
471: public void reinitialize()
472: throws IOException
473: {
474: send(REIN);
475: FTPResponse response = getResponse();
476: switch (response.getCode())
477: {
478: case 220:
479: if (dtp != null)
480: {
481: dtp.complete();
482: dtp = null;
483: }
484: break;
485: default:
486: throw new FTPException(response);
487: }
488: }
489:
490:
495: public void logout()
496: throws IOException
497: {
498: send(QUIT);
499: try
500: {
501: getResponse();
502: }
503: catch (IOException e)
504: {
505: }
506: if (dtp != null)
507: {
508: dtp.complete();
509: dtp = null;
510: }
511: try
512: {
513: socket.close();
514: }
515: catch (IOException e)
516: {
517: }
518: }
519:
520:
523: protected void initialiseDTP()
524: throws IOException
525: {
526: if (dtp != null)
527: {
528: dtp.complete();
529: dtp = null;
530: }
531:
532: InetAddress localhost = socket.getLocalAddress();
533: if (passive)
534: {
535: send(PASV);
536: FTPResponse response = getResponse();
537: switch (response.getCode())
538: {
539: case 227:
540: String message = response.getMessage();
541: try
542: {
543: int start = message.indexOf(',');
544: char c = message.charAt(start - 1);
545: while (c >= 0x30 && c <= 0x39)
546: {
547: c = message.charAt((--start) - 1);
548: }
549: int mid1 = start;
550: for (int i = 0; i < 4; i++)
551: {
552: mid1 = message.indexOf(',', mid1 + 1);
553: }
554: int mid2 = message.indexOf(',', mid1 + 1);
555: if (mid1 == -1 || mid2 < mid1)
556: {
557: throw new ProtocolException("Malformed 227: " +
558: message);
559: }
560: int end = mid2;
561: c = message.charAt(end + 1);
562: while (c >= 0x30 && c <= 0x39)
563: {
564: c = message.charAt((++end) + 1);
565: }
566:
567: String address =
568: message.substring(start, mid1).replace(',', '.');
569: int port_hi =
570: Integer.parseInt(message.substring(mid1 + 1, mid2));
571: int port_lo =
572: Integer.parseInt(message.substring(mid2 + 1, end + 1));
573: int port = (port_hi << 8) | port_lo;
574:
575:
577: dtp = new PassiveModeDTP(address, port, localhost,
578: connectionTimeout, timeout);
579: break;
580: }
581: catch (ArrayIndexOutOfBoundsException e)
582: {
583: throw new ProtocolException(e.getMessage() + ": " +
584: message);
585: }
586: catch (NumberFormatException e)
587: {
588: throw new ProtocolException(e.getMessage() + ": " +
589: message);
590: }
591: default:
592: throw new FTPException(response);
593: }
594: }
595: else
596: {
597:
598: int port = socket.getLocalPort() + 1;
599: int tries = 0;
600:
601: while (dtp == null)
602: {
603: try
604: {
605: dtp = new ActiveModeDTP(localhost, port,
606: connectionTimeout, timeout);
607:
608: }
609: catch (BindException e)
610: {
611: port++;
612: tries++;
613: if (tries > 9)
614: {
615: throw e;
616: }
617: }
618: }
619:
620:
621: StringBuffer buf = new StringBuffer(PORT);
622: buf.append(' ');
623:
624: byte[] address = localhost.getAddress();
625: for (int i = 0; i < address.length; i++)
626: {
627: int a =(int) address[i];
628: if (a < 0)
629: {
630: a += 0x100;
631: }
632: buf.append(a);
633: buf.append(',');
634: }
635: int port_hi =(port & 0xff00) >> 8;
636: int port_lo =(port & 0x00ff);
637: buf.append(port_hi);
638: buf.append(',');
639: buf.append(port_lo);
640: send(buf.toString());
641:
642: FTPResponse response = getResponse();
643: switch (response.getCode())
644: {
645: case 200:
646: break;
647: default:
648: dtp.abort();
649: dtp = null;
650: throw new FTPException(response);
651: }
652: }
653: dtp.setTransferMode(transferMode);
654: }
655:
656:
660: public void setPassive(boolean flag)
661: throws IOException
662: {
663: if (passive != flag)
664: {
665: passive = flag;
666: initialiseDTP();
667: }
668: }
669:
670:
674: public int getRepresentationType()
675: {
676: return representationType;
677: }
678:
679:
683: public void setRepresentationType(int type)
684: throws IOException
685: {
686: StringBuffer buf = new StringBuffer(TYPE);
687: buf.append(' ');
688: switch (type)
689: {
690: case TYPE_ASCII:
691: buf.append('A');
692: break;
693: case TYPE_EBCDIC:
694: buf.append('E');
695: break;
696: case TYPE_BINARY:
697: buf.append('I');
698: break;
699: default:
700: throw new IllegalArgumentException(Integer.toString(type));
701: }
702:
703:
704: send(buf.toString());
705: FTPResponse response = getResponse();
706: switch (response.getCode())
707: {
708: case 200:
709: representationType = type;
710: break;
711: default:
712: throw new FTPException(response);
713: }
714: }
715:
716:
720: public int getFileStructure()
721: {
722: return fileStructure;
723: }
724:
725:
729: public void setFileStructure(int structure)
730: throws IOException
731: {
732: StringBuffer buf = new StringBuffer(STRU);
733: buf.append(' ');
734: switch (structure)
735: {
736: case STRUCTURE_FILE:
737: buf.append('F');
738: break;
739: case STRUCTURE_RECORD:
740: buf.append('R');
741: break;
742: case STRUCTURE_PAGE:
743: buf.append('P');
744: break;
745: default:
746: throw new IllegalArgumentException(Integer.toString(structure));
747: }
748: send(buf.toString());
749: FTPResponse response = getResponse();
750: switch (response.getCode())
751: {
752: case 200:
753: fileStructure = structure;
754: break;
755: default:
756: throw new FTPException(response);
757: }
758: }
759:
760:
764: public int getTransferMode()
765: {
766: return transferMode;
767: }
768:
769:
773: public void setTransferMode(int mode)
774: throws IOException
775: {
776: StringBuffer buf = new StringBuffer(MODE);
777: buf.append(' ');
778: switch (mode)
779: {
780: case MODE_STREAM:
781: buf.append('S');
782: break;
783: case MODE_BLOCK:
784: buf.append('B');
785: break;
786: case MODE_COMPRESSED:
787: buf.append('C');
788: break;
789: default:
790: throw new IllegalArgumentException(Integer.toString(mode));
791: }
792: send(buf.toString());
793: FTPResponse response = getResponse();
794: switch (response.getCode())
795: {
796: case 200:
797: transferMode = mode;
798: if (dtp != null)
799: {
800: dtp.setTransferMode(mode);
801: }
802: break;
803: default:
804: throw new FTPException(response);
805: }
806: }
807:
808:
813: public InputStream retrieve(String filename)
814: throws IOException
815: {
816: if (dtp == null || transferMode == MODE_STREAM)
817: {
818: initialiseDTP();
819: }
820:
835: String cmd = RETR + ' ' + filename;
836: send(cmd);
837: FTPResponse response = getResponse();
838: switch (response.getCode())
839: {
840: case 125:
841: case 150:
842: return dtp.getInputStream();
843: default:
844: throw new FTPException(response);
845: }
846: }
847:
848:
855: public OutputStream store(String filename)
856: throws IOException
857: {
858: if (dtp == null || transferMode == MODE_STREAM)
859: {
860: initialiseDTP();
861: }
862: String cmd = STOR + ' ' + filename;
863: send(cmd);
864: FTPResponse response = getResponse();
865: switch (response.getCode())
866: {
867: case 125:
868: case 150:
869: return dtp.getOutputStream();
870: default:
871: throw new FTPException(response);
872: }
873: }
874:
875:
882: public OutputStream append(String filename)
883: throws IOException
884: {
885: if (dtp == null || transferMode == MODE_STREAM)
886: {
887: initialiseDTP();
888: }
889: String cmd = APPE + ' ' + filename;
890: send(cmd);
891: FTPResponse response = getResponse();
892: switch (response.getCode())
893: {
894: case 125:
895: case 150:
896: return dtp.getOutputStream();
897: default:
898: throw new FTPException(response);
899: }
900: }
901:
902:
909: public void allocate(long size)
910: throws IOException
911: {
912: String cmd = ALLO + ' ' + size;
913: send(cmd);
914: FTPResponse response = getResponse();
915: switch (response.getCode())
916: {
917: case 200:
918: case 202:
919: break;
920: default:
921: throw new FTPException(response);
922: }
923: }
924:
925:
931: public boolean rename(String oldName, String newName)
932: throws IOException
933: {
934: String cmd = RNFR + ' ' + oldName;
935: send(cmd);
936: FTPResponse response = getResponse();
937: switch (response.getCode())
938: {
939: case 450:
940: case 550:
941: return false;
942: case 350:
943: break;
944: default:
945: throw new FTPException(response);
946: }
947: cmd = RNTO + ' ' + newName;
948: send(cmd);
949: response = getResponse();
950: switch (response.getCode())
951: {
952: case 250:
953: return true;
954: case 450:
955: case 550:
956: return false;
957: default:
958: throw new FTPException(response);
959: }
960: }
961:
962:
966: public boolean abort()
967: throws IOException
968: {
969: send(ABOR);
970: FTPResponse response = getResponse();
971:
972: if (dtp != null)
973: {
974: dtp.abort();
975: }
976: switch (response.getCode())
977: {
978: case 226:
979: return false;
980: case 426:
981: response = getResponse();
982: if (response.getCode() == 226)
983: {
984: return true;
985: }
986:
987: default:
988: throw new FTPException(response);
989: }
990: }
991:
992:
996: public boolean delete(String filename)
997: throws IOException
998: {
999: String cmd = DELE + ' ' + filename;
1000: send(cmd);
1001: FTPResponse response = getResponse();
1002: switch (response.getCode())
1003: {
1004: case 250:
1005: return true;
1006: case 450:
1007: case 550:
1008: return false;
1009: default:
1010: throw new FTPException(response);
1011: }
1012: }
1013:
1014:
1019: public boolean removeDirectory(String pathname)
1020: throws IOException
1021: {
1022: String cmd = RMD + ' ' + pathname;
1023: send(cmd);
1024: FTPResponse response = getResponse();
1025: switch (response.getCode())
1026: {
1027: case 250:
1028: return true;
1029: case 550:
1030: return false;
1031: default:
1032: throw new FTPException(response);
1033: }
1034: }
1035:
1036:
1041: public boolean makeDirectory(String pathname)
1042: throws IOException
1043: {
1044: String cmd = MKD + ' ' + pathname;
1045: send(cmd);
1046: FTPResponse response = getResponse();
1047: switch (response.getCode())
1048: {
1049: case 257:
1050: return true;
1051: case 550:
1052: return false;
1053: default:
1054: throw new FTPException(response);
1055: }
1056: }
1057:
1058:
1061: public String getWorkingDirectory()
1062: throws IOException
1063: {
1064: send(PWD);
1065: FTPResponse response = getResponse();
1066: switch (response.getCode())
1067: {
1068: case 257:
1069: String message = response.getMessage();
1070: if (message.charAt(0) == '"')
1071: {
1072: int end = message.indexOf('"', 1);
1073: if (end == -1)
1074: {
1075: throw new ProtocolException(message);
1076: }
1077: return message.substring(1, end);
1078: }
1079: else
1080: {
1081: int end = message.indexOf(' ');
1082: if (end == -1)
1083: {
1084: return message;
1085: }
1086: else
1087: {
1088: return message.substring(0, end);
1089: }
1090: }
1091: default:
1092: throw new FTPException(response);
1093: }
1094: }
1095:
1096:
1105: public InputStream list(String pathname)
1106: throws IOException
1107: {
1108: if (dtp == null || transferMode == MODE_STREAM)
1109: {
1110: initialiseDTP();
1111: }
1112: if (pathname == null)
1113: {
1114: send(LIST);
1115: }
1116: else
1117: {
1118: String cmd = LIST + ' ' + pathname;
1119: send(cmd);
1120: }
1121: FTPResponse response = getResponse();
1122: switch (response.getCode())
1123: {
1124: case 125:
1125: case 150:
1126: return dtp.getInputStream();
1127: default:
1128: throw new FTPException(response);
1129: }
1130: }
1131:
1132:
1139: public List nameList(String pathname)
1140: throws IOException
1141: {
1142: if (dtp == null || transferMode == MODE_STREAM)
1143: {
1144: initialiseDTP();
1145: }
1146: if (pathname == null)
1147: {
1148: send(NLST);
1149: }
1150: else
1151: {
1152: String cmd = NLST + ' ' + pathname;
1153: send(cmd);
1154: }
1155: FTPResponse response = getResponse();
1156: switch (response.getCode())
1157: {
1158: case 125:
1159: case 150:
1160: InputStream in = dtp.getInputStream();
1161: in = new BufferedInputStream(in);
1162: in = new CRLFInputStream(in);
1163: LineInputStream li = new LineInputStream(in);
1164: List ret = new ArrayList();
1165: for (String line = li.readLine();
1166: line != null;
1167: line = li.readLine())
1168: {
1169: ret.add(line);
1170: }
1171: li.close();
1172: return ret;
1173: default:
1174: throw new FTPException(response);
1175: }
1176: }
1177:
1178:
1181: public String system()
1182: throws IOException
1183: {
1184: send(SYST);
1185: FTPResponse response = getResponse();
1186: switch (response.getCode())
1187: {
1188: case 215:
1189: String message = response.getMessage();
1190: int end = message.indexOf(' ');
1191: if (end == -1)
1192: {
1193: return message;
1194: }
1195: else
1196: {
1197: return message.substring(0, end);
1198: }
1199: default:
1200: throw new FTPException(response);
1201: }
1202: }
1203:
1204:
1209: public void noop()
1210: throws IOException
1211: {
1212: send(NOOP);
1213: FTPResponse response = getResponse();
1214: switch (response.getCode())
1215: {
1216: case 200:
1217: break;
1218: default:
1219: throw new FTPException(response);
1220: }
1221: }
1222:
1223:
1224:
1225:
1230: protected void send(String cmd)
1231: throws IOException
1232: {
1233: byte[] data = cmd.getBytes(US_ASCII);
1234: out.write(data);
1235: out.writeln();
1236: out.flush();
1237: }
1238:
1239:
1244: protected FTPResponse getResponse()
1245: throws IOException
1246: {
1247: FTPResponse response = readResponse();
1248: if (response.getCode() == 226)
1249: {
1250: if (dtp != null)
1251: {
1252: dtp.transferComplete();
1253: }
1254: response = readResponse();
1255: }
1256: return response;
1257: }
1258:
1259:
1262: protected FTPResponse readResponse()
1263: throws IOException
1264: {
1265: String line = in.readLine();
1266: if (line == null)
1267: {
1268: throw new ProtocolException( "EOF");
1269: }
1270: if (line.length() < 4)
1271: {
1272: throw new ProtocolException(line);
1273: }
1274: int code = parseCode(line);
1275: if (code == -1)
1276: {
1277: throw new ProtocolException(line);
1278: }
1279: char c = line.charAt(3);
1280: if (c == ' ')
1281: {
1282: return new FTPResponse(code, line.substring(4));
1283: }
1284: else if (c == '-')
1285: {
1286: StringBuffer buf = new StringBuffer(line.substring(4));
1287: buf.append('\n');
1288: while(true)
1289: {
1290: line = in.readLine();
1291: if (line == null)
1292: {
1293: throw new ProtocolException("EOF");
1294: }
1295: if (line.length() >= 4 &&
1296: line.charAt(3) == ' ' &&
1297: parseCode(line) == code)
1298: {
1299: return new FTPResponse(code, line.substring(4),
1300: buf.toString());
1301: }
1302: else
1303: {
1304: buf.append(line);
1305: buf.append('\n');
1306: }
1307: }
1308: }
1309: else
1310: {
1311: throw new ProtocolException(line);
1312: }
1313: }
1314:
1315:
1319: static final int parseCode(String line)
1320: {
1321: char[] c = { line.charAt(0), line.charAt(1), line.charAt(2) };
1322: int ret = 0;
1323: for (int i = 0; i < 3; i++)
1324: {
1325: int digit =((int) c[i]) - 0x30;
1326: if (digit < 0 || digit > 9)
1327: {
1328: return -1;
1329: }
1330:
1331: switch (i)
1332: {
1333: case 0:
1334: ret +=(100 * digit);
1335: break;
1336: case 1:
1337: ret +=(10 * digit);
1338: break;
1339: case 2:
1340: ret += digit;
1341: break;
1342: }
1343: }
1344: return ret;
1345: }
1346:
1347: }