      1: <?php
      2: /**
      3:  * FTP Client for PHP
      4:  *
      5:  * @package FTPClient
      6:  * @version 1.0
      7:  *
      8:  * @copyright Melih Ucar
      9:  * @author Melih Ucar
     10:  * @license http://opensource.org/licenses/MIT (The MIT License)
     11:  *
     12:  * Copyright (c) 2013, Melih Ucar (http://www.melihucar.net/)
     13:  *
     14:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
     15:  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
     16:  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     17:  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     18:  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
     19:  * OR OTHER DEALINGS IN THE SOFTWARE.
     20:  */
     21: class FTPClient
     22: {
     23:
     24:     // Const variables
     25:     const ASCII = FTP_ASCII;
     26:     const BINARY = FTP_BINARY;
     27:
     28:     const TIMEOUT_SEC = FTP_TIMEOUT_SEC;
     29:     const AUTOSEEK = FTP_AUTOSEEK;
     30:
     31:     /**
     32:      * FTP connection
     33:      * @var Resource
     34:      */
     35:     private $connection = null;
     36:
     37:     /**
     38:      * Constructor
     39:      *
     40:      * Checks if ftp extension is loaded.
     41:      */
     42:     public function FTPClient()
     43:     {
     44:         if ( !extension_loaded('ftp') ) {
     45:             throw new Exception('FTP extension is not loaded!');
     46:         }
     47:     }
     48:
     49:     /**
     50:      * Opens a FTP connection
     51:      *
     52:      * @param string $host
     53:      * @param bool $ssl
     54:      * @param int $port
     55:      * @param int $timeout
     56:      *
     57:      * @return FTPClient
     58:      */
     59:     public function connect($host, $ssl = false, $port = 21, $timeout = 90)
     60:     {
     61:         if ($ssl) {
     62:             $this->connection = @ftp_ssl_connect($host, $port, $timeout);
     63:         } else {
     64:             $this->connection = @ftp_connect($host, $port, $timeout);
     65:         }
     66:
     67:         if ($this->connection == null) {
     68:             throw new Exception('Unable to connect');
     69:         } else {
     70:             return $this;
     71:         }
     72:     }
     73:
     74:     /**
     75:      * Logins to FTP Server
     76:      *
     77:      * @param string $username
     78:      * @param string $password
     79:      *
     80:      * @return FTPClient
     81:      */
     82:     public function login($username = 'anonymous', $password = '')
     83:     {
     84:         $result = @ftp_login($this->connection, $username, $password);
     85:
     86:         if ($result === false) {
     87:             throw new Exception('Login incorrect');
     88:         } else {
     89:             return $this;
     90:         }
     91:     }
     92:
     93:     /**
     94:      * Closes FTP connection
     95:      *
     96:      * @return void
     97:      */
     98:     public function close()
     99:     {
    100:         $result = @ftp_close($this->connection);
    101:
    102:         if ($result === false) {
    103:             throw new Exception('Unable to close connection');
    104:         }
    105:     }
    106:
    107:     /**
    108:      * Changes passive mode,,,
    109:      *
    110:      * @param bool $passive
    111:      *
    112:      * @return FTPClient,
    113:      */
    114:     public function passive($passive = true)
    115:     {
    116:         $result = @ftp_pasv($this->connection, $passive);
    117:
    118:         if ($result === false) {
    119:             throw new Exception('Unable to change passive mode');
    120:         }
    121:
    122:         return $this;
    123:     }
    124:
    125:     /**
    126:      * Changes the current directory to the specified one
    127:      *
    128:      * @return FTPClient
    129:      */
    130:     public function changeDirectory($directory)
    131:     {
    132:         $result = @ftp_chdir($this->connection, $directory);
    133:
    134:         if ($result === false) {
    135:             throw new Exception('Unable to change directory');
    136:         }
    137:
    138:         return $this;
    139:     }
    140:
    141:     /**
    142:      * Changes to the parent directory
    143:      *
    144:      * @return FTPClient
    145:      */
    146:     public function parentDirectory()
    147:     {
    148:         $result = @ftp_cdup($this->connection);
    149:
    150:         if ($result === false) {
    151:             throw new Exception('Unable to get parent folder');
    152:         }
    153:
    154:         return $this;
    155:     }
    156:
    157:     /**
    158:      * Returns the current directory name
    159:      *
    160:      * @return string
    161:      */
    162:     public function getDirectory()
    163:     {
    164:         $result = @ftp_pwd($this->connection);
    165:
    166:         if ($result === false) {
    167:             throw new Exception('Unable to get directory name');
    168:         }
    169:
    170:         return $result;
    171:     }
    172:
    173:     /**
    174:      * Creates a directory
    175:      *
    176:      * @param string $directory
    177:      *
    178:      * @return FTPClient
    179:      */
    180:     public function createDirectory($directory)
    181:     {
    182:         $result = @ftp_mkdir($this->connection, $directory);
    183:
    184:         if ($result === false) {
    185:             throw new Exception('Unable to create directory');
    186:         }
    187:
    188:         return $this;
    189:     }
    190:
    191:     /**
    192:      * Removes a directory
    193:      *
    194:      * @param string $directory
    195:      *
    196:      * @return FTPClient
    197:      */
    198:     public function removeDirectory($directory)
    199:     {
    200:         $result = @ftp_rmdir($this->connection, $directory);
    201:
    202:         if ($result === false) {
    203:             throw new Exception('Unable to remove directory');
    204:         }
    205:
    206:         return $this;
    207:     }
    208:
    209:     /**
    210:      * Returns a list of files in the given directory
    211:      *
    212:      * @param string $directory
    213:      *
    214:      * @return array
    215:      */
    216:     public function listDirectory($directory)
    217:     {
    218:         $result = @ftp_nlist($this->connection, $directory);
    219:         asort($result);
    220:
    221:         if ($result === false) {
    222:             throw new Exception('Unable to list directory');
    223:         }
    224:
    225:         return $result;
    226:     }
    227:
    228:     /**
    229:      * Deletes a file on the FTP server
    230:      *
    231:      * @param string $path
    232:      *
    233:      * @return FTPClient
    234:      */
    235:     public function delete($path)
    236:     {
    237:         $result = @ftp_delete($this->connection, $path);
    238:
    239:         if ($result === false) {
    240:             throw new Exception('Unable to get parent folder');
    241:         }
    242:
    243:         return $this;
    244:     }
    245:
    246:     /**
    247:      * Returns the size of the given file.
    248:      * Return -1 on error
    249:      *
    250:      * @param string $remoteFile
    251:      *
    252:      * @return int
    253:      *
    254:      */
    255:     public function size($remoteFile)
    256:     {
    257:         $size = @ftp_size($this->connection, $remoteFile);
    258:
    259:         if ($size === -1) {
    260:             throw new Exception('Unable to get file size');
    261:         }
    262:
    263:         return $size;
    264:     }
    265:
    266:     /**
    267:      * Returns the last modified time of the given file.
    268:      * Return -1 on error
    269:      *
    270:      * @param string $remoteFile
    271:      *
    272:      * @return int
    273:      *
    274:      */
    275:     public function modifiedTime($remoteFile, $format = null)
    276:     {
    277:         $time = ftp_mdtm($this->connection, $remoteFile);
    278:
    279:         if ( $time !== -1 && $format !== null ) {
    280:             return date($format, $time);
    281:         } else {
    282:             return $time;
    283:         }
    284:     }
    285:
    286:     /**
    287:      * Renames a file or a directory on the FTP server
    288:      *
    289:      * @param string $currentName
    290:      * @param string $newName
    291:      *
    292:      * @return bool
    293:      */
    294:     public function rename($currentName, $newName)
    295:     {
    296:         $result = @ftp_rename($this->connection, $currentName, $newName);
    297:
    298:         return $result;
    299:     }
    300:
    301:     /**
    302:      * Downloads a file from the FTP server
    303:      *
    304:      * @param string $localFile
    305:      * @param string $remoteFile
    306:      * @param int $mode
    307:      * @param int $resumepos
    308:      *
    309:      * @return FTPClient
    310:      */
    311:     public function get($localFile, $remoteFile, $mode = FTPClient::ASCII, $resumePosision = 0)
    312:     {
    313:         $result = @ftp_get($this->connection, $localFile, $remoteFile, $mode, $resumePosision);
    314:
    315:         if ($result === false) {
    316:             throw new Exception('Unable to get file');
    317:         }
    318:
    319:         return $this;
    320:     }
    321:
    322:     /**
    323:      * Uploads from an open file to the FTP server
    324:      *
    325:      * @param string $remoteFile
    326:      * @param string $localFile
    327:      * @param int $mode
    328:      * @param int $startPosision
    329:      *
    330:      * @return FTPClient
    331:      */
    332:     public function put($remoteFile, $localFile, $mode = FTPClient::ASCII, $startPosision = 0)
    333:     {
    334:         $result = @ftp_put($this->connection, $remoteFile, $localFile, $mode, $startPosision);
    335:
    336:         if ($result === false) {
    337:             throw new Exception('Unable to put file');
    338:         }
    339:
    340:         return $this;
    341:     }
    342:
    343:     /**
    344:      * Downloads a file from the FTP server and saves to an open file
    345:      *
    346:      * @param resource $handle
    347:      * @param string $remoteFile
    348:      * @param int $mode
    349:      * @param int $resumepos
    350:      *
    351:      * @return FTPClient
    352:      */
    353:     public function fget(resource $handle, $remoteFile, $mode = FTPClient::ASCII, $resumePosision = 0)
    354:     {
    355:         $result = @ftp_fget($this->connection, $handle, $remoteFile, $mode, $resumePosision);
    356:
    357:         if ($result === false) {
    358:             throw new Exception('Unable to get file');
    359:         }
    360:
    361:         return $this;
    362:     }
    363:
    364:     /**
    365:      * Uploads from an open file to the FTP server
    366:      *
    367:      * @param string $remoteFile
    368:      * @param resource $handle
    369:      * @param int $mode
    370:      * @param int $startPosision
    371:      *
    372:      * @return FTPClient
    373:      */
    374:     public function fput($remoteFile, resource $handle, $mode = FTPClient::ASCII, $startPosision = 0)
    375:     {
    376:         $result = @ftp_fput($this->connection, $remoteFile, $handle, $mode, $startPosision);
    377:
    378:         if ($result === false) {
    379:             throw new Exception('Unable to put file');
    380:         }
    381:
    382:         return $this;
    383:     }
    384:
    385:     /**
    386:      * Retrieves various runtime behaviours of the current FTP stream
    387:      * TIMEOUT_SEC | AUTOSEEK
    388:      *
    389:      * @param mixed $option
    390:      *
    391:      * @return mixed
    392:      */
    393:     public function getOption($option)
    394:     {
    395:         switch ($option) {
    396:             case FTPClient::TIMEOUT_SEC:
    397:             case FTPClient::AUTOSEEK:
    398:                 $result = @ftp_get_option($this->connection, $option);
    399:
    400:                 return $result;
    401:                 break;
    402:
    403:             default:
    404:                 throw new Exception('Unsupported option');
    405:                 break;
    406:         }
    407:     }
    408:
    409:     /**
    410:      * Set miscellaneous runtime FTP options
    411:      * TIMEOUT_SEC | AUTOSEEK
    412:      *
    413:      * @param mixed $option
    414:      * @param mixed $value
    415:      *
    416:      * @return mixed
    417:      */
    418:     public function setOption($option, $value)
    419:     {
    420:         switch ($option) {
    421:             case FTPClient::TIMEOUT_SEC:
    422:                 if ($value <= 0) {
    423:                     throw new Exception('Timeout value must be greater than zero');
    424:                 }
    425:                 break;
    426:
    427:             case FTPClient::AUTOSEEK:
    428:                 if (!is_bool($value)) {
    429:                     throw new Exception('Autoseek value must be boolean');
    430:                 }
    431:                 break;
    432:
    433:             default:
    434:                 throw new Exception('Unsupported option');
    435:                 break;
    436:         }
    437:
    438:         return @ftp_set_option($this->connection, $option, $val);
    439:     }
    440:
    441:     /**
    442:      * Allocates space for a file to be uploaded
    443:      *
    444:      * @param int $filesize
    445:      *
    446:      * @return FTPClient
    447:      */
    448:     public function allocate($filesize)
    449:     {
    450:         $result = @ftp_alloc($this->connection, $size);
    451:
    452:         if ($result === false) {
    453:             throw new Exception('Unable to allocate');
    454:         }
    455:
    456:         return $this;
    457:     }
    458:
    459:     /**
    460:      * Set permissions on a file via FTP
    461:      *
    462:      * @param int $mode
    463:      * @param string $filename
    464:      *
    465:      * @return FTPClient
    466:      */
    467:     public function chmod($mode, $filename)
    468:     {
    469:         $result = @ftp_chmod($this->connection, $mode, $filename);
    470:
    471:         if ($result === false) {
    472:             throw new Exception('Unable to change permissions');
    473:         }
    474:
    475:         return $this;
    476:     }
    477:
    478:     /**
    479:      * Requests execution of a command on the FTP server
    480:      *
    481:      * @param string $command
    482:      *
    483:      * @return FTPClient
    484:      */
    485:     public function exec($command)
    486:     {
    487:         $result = @ftp_exec($this->connection, $command);
    488:
    489:         if ($result === false) {
    490:             throw new Exception('Unable to exec command');
    491:         }
    492:
    493:         return $this;
    494:     }
    495:
    496:     /**
    497:      * Destructor
    498:      */
    499:     public function __destruct()
    500:     {
    501:         $this->close();
    502:     }
    503: }