1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.gateway.ftp.adminssl;
21
22 import io.netty.buffer.ByteBuf;
23 import io.netty.buffer.Unpooled;
24 import io.netty.channel.Channel;
25 import io.netty.channel.ChannelFuture;
26 import io.netty.channel.ChannelHandlerContext;
27 import io.netty.channel.SimpleChannelInboundHandler;
28 import io.netty.handler.codec.http.DefaultFullHttpResponse;
29 import io.netty.handler.codec.http.FullHttpRequest;
30 import io.netty.handler.codec.http.FullHttpResponse;
31 import io.netty.handler.codec.http.HttpHeaderNames;
32 import io.netty.handler.codec.http.HttpHeaderValues;
33 import io.netty.handler.codec.http.HttpMethod;
34 import io.netty.handler.codec.http.HttpResponse;
35 import io.netty.handler.codec.http.HttpResponseStatus;
36 import io.netty.handler.codec.http.HttpUtil;
37 import io.netty.handler.codec.http.HttpVersion;
38 import io.netty.handler.codec.http.QueryStringDecoder;
39 import io.netty.handler.codec.http.cookie.Cookie;
40 import io.netty.handler.codec.http.cookie.DefaultCookie;
41 import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
42 import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
43 import io.netty.handler.traffic.TrafficCounter;
44 import org.waarp.common.command.ReplyCode;
45 import org.waarp.common.command.exception.CommandAbstractException;
46 import org.waarp.common.crypto.ssl.WaarpSslUtility;
47 import org.waarp.common.database.DbAdmin;
48 import org.waarp.common.database.DbPreparedStatement;
49 import org.waarp.common.database.DbSession;
50 import org.waarp.common.database.exception.WaarpDatabaseException;
51 import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
52 import org.waarp.common.database.exception.WaarpDatabaseSqlException;
53 import org.waarp.common.file.DirInterface;
54 import org.waarp.common.logging.WaarpLogger;
55 import org.waarp.common.logging.WaarpLoggerFactory;
56 import org.waarp.common.utility.ThreadLocalRandom;
57 import org.waarp.common.utility.Version;
58 import org.waarp.common.utility.WaarpStringUtils;
59 import org.waarp.ftp.core.session.FtpSession;
60 import org.waarp.ftp.core.utils.FtpChannelUtils;
61 import org.waarp.gateway.ftp.config.FileBasedConfiguration;
62 import org.waarp.gateway.ftp.control.FtpConstraintLimitHandler;
63 import org.waarp.gateway.ftp.database.DbConstantFtp;
64 import org.waarp.gateway.ftp.database.data.DbTransferLog;
65 import org.waarp.gateway.ftp.exec.AbstractExecutor;
66 import org.waarp.gateway.ftp.exec.AbstractExecutor.CommandExecutor;
67 import org.waarp.gateway.ftp.file.FileBasedAuth;
68 import org.waarp.gateway.kernel.http.HttpWriteCacheEnable;
69
70 import java.io.IOException;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Set;
74 import java.util.concurrent.ConcurrentHashMap;
75
76
77
78
79 public class HttpSslHandler
80 extends SimpleChannelInboundHandler<FullHttpRequest> {
81 private static final String XXXFILEXXX = "XXXFILEXXX";
82 private static final String ACTION2 = "ACTION";
83 private static final String XXXRESULTXXX = "XXXRESULTXXX";
84
85
86
87 private static final WaarpLogger logger =
88 WaarpLoggerFactory.getLogger(HttpSslHandler.class);
89
90
91
92 private static final ConcurrentHashMap<String, FileBasedAuth> sessions =
93 new ConcurrentHashMap<String, FileBasedAuth>();
94 private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
95
96 private final FtpSession ftpSession =
97 new FtpSession(FileBasedConfiguration.fileBasedConfiguration, null);
98 private FileBasedAuth authentHttp = new FileBasedAuth(ftpSession);
99
100 private FullHttpRequest request;
101 private boolean newSession;
102 private Cookie admin;
103 private final StringBuilder responseContent = new StringBuilder();
104 private String uriRequest;
105 private Map<String, List<String>> params;
106 private boolean forceClose;
107 private boolean shutdown;
108
109 private static final String FTPSESSIONString = "FTPSESSION";
110
111 private enum REQUEST {
112 Logon("Logon.html"), index("index.html"), error("error.html"),
113 Transfer("Transfer_head.html", "Transfer_body.html", "Transfer_end.html"),
114 Rule("Rule.html"),
115 User("User_head.html", "User_body.html", "User_end.html"),
116 System("System.html");
117
118 private final String header;
119 private final String body;
120 private final String end;
121
122
123
124
125
126
127 REQUEST(final String uniquefile) {
128 header = uniquefile;
129 body = null;
130 end = null;
131 }
132
133
134
135
136
137
138 REQUEST(final String header, final String body, final String end) {
139 this.header = header;
140 this.body = body;
141 this.end = end;
142 }
143
144
145
146
147
148
149 public final String readFileUnique() {
150 return WaarpStringUtils.readFile(
151 FileBasedConfiguration.fileBasedConfiguration.getHttpBasePath() +
152 header);
153 }
154
155 public final String readHeader() {
156 return WaarpStringUtils.readFile(
157 FileBasedConfiguration.fileBasedConfiguration.getHttpBasePath() +
158 header);
159 }
160
161 public final String readBody() {
162 return WaarpStringUtils.readFile(
163 FileBasedConfiguration.fileBasedConfiguration.getHttpBasePath() +
164 body);
165 }
166
167 public final String readEnd() {
168 return WaarpStringUtils.readFile(
169 FileBasedConfiguration.fileBasedConfiguration.getHttpBasePath() +
170 end);
171 }
172 }
173
174 public static final int LIMITROW = 48;
175
176
177
178
179
180
181 private DbSession dbSession;
182
183 private String getTrimValue(final String varname) {
184 String value = params.get(varname).get(0).trim();
185 if (value.length() == 0) {
186 value = null;
187 }
188 return value;
189 }
190
191 private String index() {
192 final String index = REQUEST.index.readFileUnique();
193 final StringBuilder builder = new StringBuilder(index);
194 WaarpStringUtils.replace(builder, "XXXLOCALXXX",
195 FileBasedConfiguration.fileBasedConfiguration.getFtpInternalConfiguration()
196 .getNumberSessions() +
197 " " + Thread.activeCount());
198 final TrafficCounter trafficCounter =
199 FileBasedConfiguration.fileBasedConfiguration.getFtpInternalConfiguration()
200 .getGlobalTrafficShapingHandler()
201 .trafficCounter();
202 WaarpStringUtils.replace(builder, "XXXBANDWIDTHXXX", "IN:" +
203 trafficCounter.lastReadThroughput() /
204 131072 +
205 "Mbits <br> OUT:" +
206 trafficCounter.lastWriteThroughput() /
207 131072 + "Mbits");
208 WaarpStringUtils.replaceAll(builder, "XXXHOSTIDXXX",
209 FileBasedConfiguration.fileBasedConfiguration.getHostId());
210 WaarpStringUtils.replaceAll(builder, "XXXADMINXXX",
211 "Administrator Connected");
212 WaarpStringUtils.replace(builder, "XXXVERSIONXXX",
213 Version.fullIdentifier());
214 return builder.toString();
215 }
216
217 private String error(final String mesg) {
218 final String index = REQUEST.error.readFileUnique();
219 return index.replace("XXXERRORMESGXXX", mesg);
220 }
221
222 private String logon() {
223 return REQUEST.Logon.readFileUnique();
224 }
225
226 private String system() {
227 getParams();
228 final FtpConstraintLimitHandler handler =
229 FileBasedConfiguration.fileBasedConfiguration.getConstraintLimitHandler();
230 if (params == null) {
231 final String system = REQUEST.System.readFileUnique();
232 final StringBuilder builder = new StringBuilder(system);
233 WaarpStringUtils.replace(builder, "XXXXCHANNELLIMITRXXX", Long.toString(
234 FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit()));
235 WaarpStringUtils.replace(builder, "XXXXCPULXXX",
236 Double.toString(handler.getCpuLimit()));
237 WaarpStringUtils.replace(builder, "XXXXCONLXXX",
238 Integer.toString(handler.getChannelLimit()));
239 WaarpStringUtils.replace(builder, XXXRESULTXXX, "");
240 return builder.toString();
241 }
242 String extraInformation = null;
243 if (params.containsKey(ACTION2)) {
244 final List<String> action = params.get(ACTION2);
245 for (final String act : action) {
246 if ("Disconnect".equalsIgnoreCase(act)) {
247 final String logon = logon();
248 newSession = true;
249 clearSession();
250 forceClose = true;
251 return logon;
252 } else if ("Shutdown".equalsIgnoreCase(act)) {
253 final String error = error("Shutdown in progress");
254 newSession = true;
255 clearSession();
256 forceClose = true;
257 shutdown = true;
258 return error;
259 } else if ("Validate".equalsIgnoreCase(act)) {
260 String bglobalr = getTrimValue("BGLOBR");
261 long lglobal =
262 FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit();
263 if (bglobalr != null) {
264 lglobal = Long.parseLong(bglobalr);
265 }
266 FileBasedConfiguration.fileBasedConfiguration.changeNetworkLimit(
267 lglobal, lglobal);
268 bglobalr = getTrimValue("CPUL");
269 double dcpu = handler.getCpuLimit();
270 if (bglobalr != null) {
271 dcpu = Double.parseDouble(bglobalr);
272 }
273 handler.setCpuLimit(dcpu);
274 bglobalr = getTrimValue("CONL");
275 int iconn = handler.getChannelLimit();
276 if (bglobalr != null) {
277 iconn = Integer.parseInt(bglobalr);
278 }
279 handler.setChannelLimit(iconn);
280 extraInformation = "Configuration Saved";
281 }
282 }
283 }
284 final String system = REQUEST.System.readFileUnique();
285 final StringBuilder builder = new StringBuilder(system);
286 WaarpStringUtils.replace(builder, "XXXXCHANNELLIMITRXXX", Long.toString(
287 FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit()));
288 WaarpStringUtils.replace(builder, "XXXXCPULXXX",
289 Double.toString(handler.getCpuLimit()));
290 WaarpStringUtils.replace(builder, "XXXXCONLXXX",
291 Integer.toString(handler.getChannelLimit()));
292 if (extraInformation != null) {
293 WaarpStringUtils.replace(builder, XXXRESULTXXX, extraInformation);
294 } else {
295 WaarpStringUtils.replace(builder, XXXRESULTXXX, "");
296 }
297 return builder.toString();
298 }
299
300 private String rule() {
301 getParams();
302 if (params == null) {
303 final String system = REQUEST.Rule.readFileUnique();
304 final StringBuilder builder = new StringBuilder(system);
305 final CommandExecutor exec = AbstractExecutor.getCommandExecutor();
306 WaarpStringUtils.replace(builder, "XXXSTCXXX",
307 exec.getStorType() + ' ' + exec.pstorCMD);
308 WaarpStringUtils.replace(builder, "XXXSTDXXX",
309 Long.toString(exec.getPstorDelay()));
310 WaarpStringUtils.replace(builder, "XXXRTCXXX",
311 exec.getRetrType() + ' ' + exec.pretrCMD);
312 WaarpStringUtils.replace(builder, "XXXRTDXXX",
313 Long.toString(exec.getPretrDelay()));
314 WaarpStringUtils.replace(builder, XXXRESULTXXX, "");
315 return builder.toString();
316 }
317 String extraInformation = null;
318 if (params.containsKey(ACTION2)) {
319 final List<String> action = params.get(ACTION2);
320 for (final String act : action) {
321 if ("Update".equalsIgnoreCase(act)) {
322 final CommandExecutor exec = AbstractExecutor.getCommandExecutor();
323 String bglobalr = getTrimValue("std");
324 long lglobal = exec.getPstorDelay();
325 if (bglobalr != null) {
326 lglobal = Long.parseLong(bglobalr);
327 }
328 exec.setPstorDelay(lglobal);
329 bglobalr = getTrimValue("rtd");
330 lglobal = exec.getPretrDelay();
331 if (bglobalr != null) {
332 lglobal = Long.parseLong(bglobalr);
333 }
334 exec.setPretrDelay(lglobal);
335 bglobalr = getTrimValue("stc");
336 String store = exec.getStorType() + ' ' + exec.pstorCMD;
337 if (bglobalr != null) {
338 store = bglobalr;
339 }
340 bglobalr = getTrimValue("rtc");
341 String retr = exec.getRetrType() + ' ' + exec.pretrCMD;
342 if (bglobalr != null) {
343 retr = bglobalr;
344 }
345 AbstractExecutor.initializeExecutor(retr, exec.getPretrDelay(), store,
346 exec.getPstorDelay());
347 extraInformation = "Configuration Saved";
348 }
349 }
350 }
351 final String system = REQUEST.Rule.readFileUnique();
352 final StringBuilder builder = new StringBuilder(system);
353 final CommandExecutor exec = AbstractExecutor.getCommandExecutor();
354 WaarpStringUtils.replace(builder, "XXXSTCXXX",
355 exec.getStorType() + ' ' + exec.pstorCMD);
356 WaarpStringUtils.replace(builder, "XXXSTDXXX",
357 Long.toString(exec.getPstorDelay()));
358 WaarpStringUtils.replace(builder, "XXXRTCXXX",
359 exec.getRetrType() + ' ' + exec.pretrCMD);
360 WaarpStringUtils.replace(builder, "XXXRTDXXX",
361 Long.toString(exec.getPretrDelay()));
362 if (extraInformation != null) {
363 WaarpStringUtils.replace(builder, XXXRESULTXXX, extraInformation);
364 } else {
365 WaarpStringUtils.replace(builder, XXXRESULTXXX, "");
366 }
367 return builder.toString();
368 }
369
370 private String transfer() {
371 getParams();
372 final String head = REQUEST.Transfer.readHeader();
373 String end = REQUEST.Transfer.readEnd();
374 String body = REQUEST.Transfer.readBody();
375 if (params == null) {
376 end = end.replace(XXXRESULTXXX, "");
377 body = FileBasedConfiguration.fileBasedConfiguration.getHtmlTransfer(body,
378 LIMITROW);
379 return head + body + end;
380 }
381 String message = "";
382 final List<String> parms = params.get(ACTION2);
383 if (parms != null) {
384 final String parm = parms.get(0);
385 boolean purgeAll = false;
386 boolean purgeCorrect = false;
387 boolean delete = false;
388 if ("PurgeCorrectTransferLogs".equalsIgnoreCase(parm)) {
389 purgeCorrect = true;
390 } else if ("PurgeAllTransferLogs".equalsIgnoreCase(parm)) {
391 purgeAll = true;
392 } else if ("Delete".equalsIgnoreCase(parm)) {
393 delete = true;
394 }
395 if (purgeCorrect || purgeAll) {
396 DbPreparedStatement preparedStatement = null;
397 ReplyCode status = null;
398 String action = "purgeAll";
399
400 if (purgeCorrect) {
401 status = ReplyCode.REPLY_226_CLOSING_DATA_CONNECTION;
402 action = "purge";
403 }
404 try {
405 preparedStatement =
406 DbTransferLog.getStatusPrepareStament(dbSession, status, 0);
407 } catch (final WaarpDatabaseNoConnectionException e) {
408 message = "Error during " + action;
409 } catch (final WaarpDatabaseSqlException e) {
410 message = "Error during " + action;
411 }
412 if (preparedStatement != null) {
413 try {
414 final FileBasedConfiguration config =
415 FileBasedConfiguration.fileBasedConfiguration;
416 final String filename =
417 config.getBaseDirectory() + DirInterface.SEPARATOR +
418 config.getAdminName() + DirInterface.SEPARATOR +
419 config.getHostId() + "_logs_" + System.currentTimeMillis() +
420 ".xml";
421 message = DbTransferLog.saveDbTransferLogFile(preparedStatement,
422 filename);
423 } finally {
424 preparedStatement.realClose();
425 }
426 }
427 } else if (delete) {
428 final String user = getTrimValue("user");
429 final String acct = getTrimValue("account");
430 final String specid = getTrimValue("specialid");
431 final long specialId = Long.parseLong(specid);
432 try {
433 final DbTransferLog log =
434 new DbTransferLog(dbSession, user, acct, specialId);
435 final FileBasedConfiguration config =
436 FileBasedConfiguration.fileBasedConfiguration;
437 final String filename =
438 config.getBaseDirectory() + DirInterface.SEPARATOR +
439 config.getAdminName() + DirInterface.SEPARATOR +
440 config.getHostId() + "_log_" + System.currentTimeMillis() +
441 ".xml";
442 message = log.saveDbTransferLog(filename);
443 } catch (final WaarpDatabaseException e) {
444 message = "Error during delete 1 Log";
445 }
446 } else {
447 message = "No Action";
448 }
449 end = end.replace(XXXRESULTXXX, message);
450 }
451 end = end.replace(XXXRESULTXXX, "");
452 body = FileBasedConfiguration.fileBasedConfiguration.getHtmlTransfer(body,
453 LIMITROW);
454 return head + body + end;
455 }
456
457 private String user() {
458 getParams();
459 final String head = REQUEST.User.readHeader();
460 String end = REQUEST.User.readEnd();
461 String body = REQUEST.User.readBody();
462 final FileBasedConfiguration config =
463 FileBasedConfiguration.fileBasedConfiguration;
464 final String filedefault =
465 config.getBaseDirectory() + DirInterface.SEPARATOR +
466 config.getAdminName() + DirInterface.SEPARATOR + "authentication.xml";
467 if (params == null) {
468 end = end.replace(XXXRESULTXXX, "");
469 end = end.replace(XXXFILEXXX, filedefault);
470 body = FileBasedConfiguration.fileBasedConfiguration.getHtmlAuth(body);
471 return head + body + end;
472 }
473 final List<String> parms = params.get(ACTION2);
474 if (parms != null) {
475 final String parm = parms.get(0);
476 if ("ImportExport".equalsIgnoreCase(parm)) {
477 String file = getTrimValue("file");
478 final String exportImport = getTrimValue("export");
479 String message = "";
480 final boolean purge;
481 purge = params.containsKey("purge");
482 final boolean replace;
483 replace = params.containsKey("replace");
484 if (file == null) {
485 file = filedefault;
486 }
487 end = end.replace(XXXFILEXXX, file);
488 if ("import".equalsIgnoreCase(exportImport)) {
489 if (!config.initializeAuthent(file, purge)) {
490 message += "Cannot initialize Authentication from " + file;
491 } else {
492 message += "Initialization of Authentication OK from " + file;
493 if (replace) {
494 if (!config.saveAuthenticationFile(
495 config.getAuthenticationFile())) {
496 message += " but cannot replace server authenticationFile";
497 } else {
498 message += " and replacement done";
499 }
500 }
501 }
502 } else {
503
504 if (!config.saveAuthenticationFile(file)) {
505 message += "Authentications CANNOT be saved into " + file;
506 } else {
507 message += "Authentications saved into " + file;
508 }
509 }
510 end = end.replace(XXXRESULTXXX, message);
511 } else {
512 end = end.replace(XXXFILEXXX, filedefault);
513 }
514 }
515 end = end.replace(XXXRESULTXXX, "");
516 body = FileBasedConfiguration.fileBasedConfiguration.getHtmlAuth(body);
517 return head + body + end;
518 }
519
520 private void getParams() {
521 if (request.method() == HttpMethod.GET) {
522 params = null;
523 } else if (request.method() == HttpMethod.POST) {
524 final ByteBuf content = request.content();
525 if (content.isReadable()) {
526 final String param = content.toString(WaarpStringUtils.UTF8);
527 final QueryStringDecoder queryStringDecoder2 =
528 new QueryStringDecoder("/?" + param);
529 params = queryStringDecoder2.parameters();
530 } else {
531 params = null;
532 }
533 }
534 }
535
536 private void clearSession() {
537 if (admin != null) {
538 final FileBasedAuth auth = sessions.remove(admin.value());
539 admin = null;
540 if (auth != null) {
541 auth.clear();
542 }
543 }
544 }
545
546 protected final void closeConnection() {
547 if (dbSession != null &&
548 dbSession != DbConstantFtp.gatewayAdmin.getSession()) {
549 DbAdmin.decHttpSession();
550 dbSession.disconnect();
551 }
552 dbSession = null;
553 }
554
555 private void checkAuthent(final ChannelHandlerContext ctx) {
556 newSession = true;
557 if (request.method() == HttpMethod.GET) {
558 final String logon = logon();
559 responseContent.append(logon);
560 clearSession();
561 writeResponse(ctx);
562 return;
563 } else if (request.method() == HttpMethod.POST) {
564 getParams();
565 if (params == null) {
566 final String logon = logon();
567 responseContent.append(logon);
568 clearSession();
569 writeResponse(ctx);
570 return;
571 }
572 }
573 boolean getMenu = false;
574 if (params.containsKey("Logon")) {
575 String name = null;
576 String password = null;
577 List<String> values;
578
579 if (params.containsKey("name")) {
580 values = params.get("name");
581 if (values != null) {
582 name = values.get(0);
583 if (name == null || name.length() == 0) {
584 getMenu = true;
585 }
586 }
587 } else {
588 getMenu = true;
589 }
590
591 if (!getMenu && params.containsKey("passwd")) {
592 values = params.get("passwd");
593 if (values != null) {
594 password = values.get(0);
595 getMenu = password == null || password.length() == 0;
596 } else {
597 getMenu = true;
598 }
599 } else {
600 getMenu = true;
601 }
602 if (!getMenu && name != null) {
603 logger.debug("Name={} vs {} Pass={} vs {}", name, name.equals(
604 FileBasedConfiguration.fileBasedConfiguration.getAdminName()),
605 password,
606 FileBasedConfiguration.fileBasedConfiguration.checkPassword(
607 password));
608 if (name.equals(
609 FileBasedConfiguration.fileBasedConfiguration.getAdminName()) &&
610 FileBasedConfiguration.fileBasedConfiguration.checkPassword(
611 password)) {
612 authentHttp.specialNoSessionAuth(
613 FileBasedConfiguration.fileBasedConfiguration.getHostId());
614 } else {
615 getMenu = true;
616 }
617 if (!authentHttp.isIdentified()) {
618 logger.info("Still not authenticated: {}", authentHttp);
619 getMenu = true;
620 }
621 }
622 } else {
623 getMenu = true;
624 }
625 if (getMenu) {
626 final String logon = logon();
627 responseContent.append(logon);
628 clearSession();
629 } else {
630 final String index = index();
631 responseContent.append(index);
632 clearSession();
633 admin = new DefaultCookie(FTPSESSIONString,
634 FileBasedConfiguration.fileBasedConfiguration.getHostId() +
635 Long.toHexString(RANDOM.nextLong()));
636 sessions.put(admin.value(), authentHttp);
637 logger.debug("CreateSession: {}}:{}", uriRequest, admin);
638 }
639 writeResponse(ctx);
640 }
641
642 @Override
643 protected void channelRead0(final ChannelHandlerContext ctx,
644 final FullHttpRequest msg) {
645 request = msg;
646 final QueryStringDecoder queryStringDecoder =
647 new QueryStringDecoder(request.uri());
648 uriRequest = queryStringDecoder.path();
649 if (uriRequest.contains("gre/") || uriRequest.contains("img/") ||
650 uriRequest.contains("res/")) {
651 HttpWriteCacheEnable.writeFile(request, ctx,
652 FileBasedConfiguration.fileBasedConfiguration.getHttpBasePath() +
653 uriRequest, FTPSESSIONString);
654 return;
655 }
656 checkSession();
657 try {
658 if (!authentHttp.isIdentified()) {
659 logger.debug("Not Authent: {}}:{}", uriRequest, authentHttp);
660 checkAuthent(ctx);
661 return;
662 }
663 String find = uriRequest;
664 if (uriRequest.charAt(0) == '/') {
665 find = uriRequest.substring(1);
666 }
667 find = find.substring(0, find.indexOf('.'));
668 REQUEST req = REQUEST.index;
669 try {
670 req = REQUEST.valueOf(find);
671 } catch (final IllegalArgumentException e1) {
672 req = REQUEST.index;
673 logger.info("NotFound: {}:{}", find, uriRequest);
674 }
675 switch (req) {
676 case System:
677 responseContent.append(system());
678 break;
679 case Rule:
680 responseContent.append(rule());
681 break;
682 case User:
683 responseContent.append(user());
684 break;
685 case Transfer:
686 responseContent.append(transfer());
687 break;
688 default:
689 responseContent.append(index());
690 break;
691 }
692 writeResponse(ctx);
693 } finally {
694 closeConnection();
695 }
696 }
697
698 private void checkSession() {
699 final String cookieString = request.headers().get(HttpHeaderNames.COOKIE);
700 if (cookieString != null) {
701 final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
702 if (!cookies.isEmpty()) {
703 for (final Cookie elt : cookies) {
704 if (elt.name().equalsIgnoreCase(FTPSESSIONString)) {
705 admin = elt;
706 break;
707 }
708 }
709 }
710 }
711
712 try {
713 dbSession = new DbSession(DbConstantFtp.gatewayAdmin, false);
714 DbAdmin.incHttpSession();
715 } catch (final WaarpDatabaseNoConnectionException e1) {
716
717 logger.warn("Use default database connection");
718 dbSession = DbConstantFtp.gatewayAdmin.getSession();
719 }
720 if (admin != null) {
721 final FileBasedAuth auth = sessions.get(admin.value());
722 if (auth != null) {
723 authentHttp = auth;
724 }
725 } else {
726 logger.info("NoSession: {}:{}", uriRequest, admin);
727 }
728 }
729
730 private void handleCookies(final HttpResponse response) {
731 final String cookieString = request.headers().get(HttpHeaderNames.COOKIE);
732 if (cookieString != null) {
733 final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
734 if (!cookies.isEmpty()) {
735
736 boolean findSession = false;
737 for (final Cookie cookie : cookies) {
738 if (cookie.name().equalsIgnoreCase(FTPSESSIONString)) {
739 if (newSession) {
740 findSession = false;
741 } else {
742 findSession = true;
743 response.headers().add(HttpHeaderNames.SET_COOKIE,
744 ServerCookieEncoder.LAX.encode(cookie));
745 }
746 } else {
747 response.headers().add(HttpHeaderNames.SET_COOKIE,
748 ServerCookieEncoder.LAX.encode(cookie));
749 }
750 }
751 newSession = false;
752 if (!findSession && admin != null) {
753 response.headers().add(HttpHeaderNames.SET_COOKIE,
754 ServerCookieEncoder.LAX.encode(admin));
755 logger.debug("AddSession: {}:{}", uriRequest, admin);
756 }
757 }
758 } else if (admin != null) {
759 logger.debug("AddSession: {}:{}", uriRequest, admin);
760 response.headers().add(HttpHeaderNames.SET_COOKIE,
761 ServerCookieEncoder.LAX.encode(admin));
762 }
763 }
764
765
766
767
768
769
770 private void writeResponse(final ChannelHandlerContext ctx) {
771
772 final ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(),
773 WaarpStringUtils.UTF8);
774 responseContent.setLength(0);
775
776
777 final boolean keepAlive = HttpUtil.isKeepAlive(request);
778 final boolean close = HttpHeaderValues.CLOSE.contentEqualsIgnoreCase(
779 request.headers().get(HttpHeaderNames.CONNECTION)) || !keepAlive ||
780 forceClose;
781
782
783 final FullHttpResponse response =
784 new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
785 buf);
786 response.headers().add(HttpHeaderNames.CONTENT_LENGTH,
787 response.content().readableBytes());
788 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
789 if (keepAlive) {
790 response.headers()
791 .set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
792 }
793 if (!close) {
794
795
796 response.headers().set(HttpHeaderNames.CONTENT_LENGTH,
797 String.valueOf(buf.readableBytes()));
798 }
799
800 handleCookies(response);
801
802
803 final ChannelFuture future = ctx.writeAndFlush(response);
804
805 if (close) {
806 future.addListener(WaarpSslUtility.SSLCLOSE);
807 }
808 if (shutdown) {
809 FtpChannelUtils.teminateServer(
810 FileBasedConfiguration.fileBasedConfiguration);
811 if (!close) {
812 future.addListener(WaarpSslUtility.SSLCLOSE);
813 }
814 }
815 }
816
817
818
819
820
821
822
823 private void sendError(final ChannelHandlerContext ctx,
824 final HttpResponseStatus status) {
825 responseContent.setLength(0);
826 responseContent.append(error(status.toString()));
827 final FullHttpResponse response =
828 new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,
829 Unpooled.copiedBuffer(
830 responseContent.toString(),
831 WaarpStringUtils.UTF8));
832 response.headers().add(HttpHeaderNames.CONTENT_LENGTH,
833 response.content().readableBytes());
834 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
835 clearSession();
836
837 ctx.channel().writeAndFlush(response).addListener(WaarpSslUtility.SSLCLOSE);
838 }
839
840 @Override
841 public void exceptionCaught(final ChannelHandlerContext ctx,
842 final Throwable cause) {
843 if (!(cause instanceof CommandAbstractException)) {
844 if (cause instanceof IOException) {
845
846 return;
847 }
848 logger.warn("Exception in HttpSslHandler: {}", cause.getMessage());
849 }
850 if (ctx.channel().isActive()) {
851 sendError(ctx, HttpResponseStatus.BAD_REQUEST);
852 }
853 }
854
855 @Override
856 public void channelActive(final ChannelHandlerContext ctx) throws Exception {
857 final Channel channel = ctx.channel();
858 logger.debug("Add channel to ssl");
859 FileBasedConfiguration.fileBasedConfiguration.getHttpChannelGroup()
860 .add(channel);
861 super.channelActive(ctx);
862 }
863 }