1 /* 2 * This file is part of Waarp Project (named also Waarp or GG). 3 * 4 * Copyright (c) 2019, Waarp SAS, and individual contributors by the @author 5 * tags. See the COPYRIGHT.txt in the distribution for a full listing of 6 * individual contributors. 7 * 8 * All Waarp Project is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or (at your 11 * option) any later version. 12 * 13 * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY 14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 15 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * Waarp . If not, see <http://www.gnu.org/licenses/>. 19 */ 20 package org.waarp.ftp.core.data.handler; 21 22 import io.netty.channel.ChannelHandler.Sharable; 23 import io.netty.channel.ChannelHandlerContext; 24 import io.netty.handler.codec.MessageToMessageCodec; 25 import org.waarp.common.exception.InvalidArgumentException; 26 import org.waarp.common.file.DataBlock; 27 import org.waarp.ftp.core.command.FtpArgumentCode.TransferStructure; 28 29 import java.util.List; 30 31 /** 32 * Third CODEC :<br> 33 * - encode/decode : takes {@link DataBlock} and transforms it to a {@link 34 * DataBlock}<br> 35 * FILE and RECORD are implemented (DataNetworkHandler will do the real job). 36 * PAGE is not implemented.<br> 37 * Note that real actions are taken in the DataNetworkHandler according to the 38 * implementation of FtpFile. 39 */ 40 @Sharable 41 class FtpDataStructureCodec 42 extends MessageToMessageCodec<DataBlock, DataBlock> { 43 /* 44 * 3.1.2. DATA STRUCTURES In addition to different representation types, FTP allows the structure of a file to 45 * be specified. Three file structures are defined in FTP: file-structure, where there is no internal 46 * structure and the file is considered to be a continuous sequence of data bytes, record-structure, where the 47 * file is made up of sequential records, and page-structure, where the file is made up of independent indexed 48 * pages. FileInterface-structure is the default to be assumed if the STRUcture command has not been used but 49 * both file and record structures must be accepted for "text" files (i.e., files with TYPE ASCII or EBCDIC) 50 * by all FTP implementations. The structure of a file will affect both the transfer mode of a file (see the 51 * Section on Transmission Modes) and the interpretation and storage of the file. The "natural" structure of a 52 * file will depend on which host stores the file. A source-code file will usually be stored on an IBM 53 * Mainframe in fixed length records but on a DEC TOPS-20 as a stream of characters partitioned into lines, 54 * for example by <CRLF>. If the transfer of files between such disparate sites is to be useful, there must be 55 * some way for one site to recognize the other's assumptions about the file. With some sites being naturally 56 * file-oriented and others naturally record-oriented there may be problems if a file with one structure is 57 * sent to a host oriented to the other. If a text file is sent with record-structure to a host which is file 58 * oriented, then that host should apply an internal transformation to the file based on the record structure. 59 * Obviously, this transformation should be useful, but it must also be invertible so that an identical file 60 * may be retrieved using record structure. In the case of a file being sent with file-structure to a 61 * record-oriented host, there exists the question of what criteria the host should use to divide the file 62 * into records which can be processed locally. If this division is necessary, the FTP implementation should 63 * use the end-of-line sequence, <CRLF> for ASCII, or <NL> for EBCDIC text files, as the delimiter. If an FTP 64 * implementation adopts this technique, it must be prepared to reverse the transformation if the file is 65 * retrieved with file-structure. 3.1.2.1. FILE STRUCTURE FileInterface structure is the default to be assumed 66 * if the STRUcture command has not been used. In file-structure there is no internal structure and the file 67 * is considered to be a continuous sequence of data bytes. 3.1.2.2. RECORD STRUCTURE Record structures must 68 * be accepted for "text" files (i.e., files with TYPE ASCII or EBCDIC) by all FTP implementations. In 69 * record-structure the file is made up of sequential records. 3.1.2.3. PAGE STRUCTURE To transmit files that 70 * are discontinuous, FTP defines a page structure. Files of this type are sometimes known as 71 * "random access files" or even as "holey files". In these files there is sometimes other information 72 * associated with the file as a whole (e.g., a file descriptor), or with a section of the file (e.g., page 73 * access controls), or both. In FTP, the sections of the file are called pages. To provide for various page 74 * sizes and associated information, each page is sent with a page header. The page header has the following 75 * defined fields: Header Length The number of logical bytes in the page header including this byte. The 76 * minimum header length is 4. Page Index The logical page number of this section of the file. This is not the 77 * transmission sequence number of this page, but the index used to identify this page of the file. Data 78 * Length The number of logical bytes in the page data. The minimum data length is 0. Page Type The type of 79 * page this is. The following page types are defined: 0 = Last Page This is used to indicate the end of a 80 * paged structured transmission. The header length must be 4, and the data length must be 0. 1 = Simple Page 81 * This is the normal type for simple paged files with no page level associated control information. The 82 * header length must be 4. 2 = Descriptor Page This type is used to transmit the descriptive information for 83 * the file as a whole. 3 = Access Controlled Page This type includes an additional header field for paged 84 * files with page level access control information. The header length must be 5. Optional Fields Further 85 * header fields may be used to supply per page control information, for example, per page access control. All 86 * fields are one logical byte in length. The logical byte size is specified by the TYPE command. See Appendix 87 * I for further details and a specific case at the page structure. A note of caution about parameters: a file 88 * must be stored and retrieved with the same parameters if the retrieved version is to be identical to the 89 * version originally transmitted. Conversely, FTP implementations must return a file identical to the 90 * original if the parameters used to store and retrieve a file are the same. 91 */ 92 /** 93 * Structure of transfer 94 */ 95 private TransferStructure structure; 96 97 /** 98 * @param structure 99 */ 100 FtpDataStructureCodec(final TransferStructure structure) { 101 this.structure = structure; 102 } 103 104 /** 105 * @return the structure 106 */ 107 public TransferStructure getStructure() { 108 return structure; 109 } 110 111 /** 112 * @param structure the structure to set 113 */ 114 public final void setStructure(final TransferStructure structure) { 115 this.structure = structure; 116 } 117 118 @Override 119 protected void encode(final ChannelHandlerContext ctx, final DataBlock msg, 120 final List<Object> out) throws Exception { 121 if (structure == TransferStructure.FILE || 122 structure == TransferStructure.RECORD) { 123 out.add(msg); 124 return; 125 } 126 // Type unimplemented 127 throw new InvalidArgumentException( 128 "Structure unimplemented in " + getClass().getName() + " codec " + 129 structure.name()); 130 } 131 132 @Override 133 protected void decode(final ChannelHandlerContext ctx, final DataBlock msg, 134 final List<Object> out) throws Exception { 135 if (structure == TransferStructure.FILE || 136 structure == TransferStructure.RECORD) { 137 out.add(msg); 138 return; 139 } 140 // Type unimplemented 141 throw new InvalidArgumentException( 142 "Structure unimplemented in " + getClass().getName() + " codec " + 143 structure.name()); 144 } 145 146 }