1#!/usr/bin/env php
2
3<?php
4
5ini_set('display_errors', 'On');
6error_reporting(E_ALL);
7
8set_time_limit(0);
9set_include_path(get_include_path() . PATH_SEPARATOR . "../../bindings/php");
10
11include 'megaapi.php';
12
13if (file_exists('vendor/autoload.php'))
14    require_once('vendor/autoload.php');
15else
16    require_once('Symfony/autoload.php');
17
18use Symfony\Component\Console\Shell;
19use Symfony\Component\Console\Application;
20use Symfony\Component\Console\Command\Command;
21use Symfony\Component\Console\Input\InputInterface;
22use Symfony\Component\Console\Output\OutputInterface;
23use Symfony\Component\Console\Input\InputArgument;
24use Symfony\Component\Console\Input\InputOption;
25
26if (!PHP_ZTS)
27{
28   print("WARNING: Your version of PHP is not thread-safe (ZTS).\nThe MEGA SDK uses a worker thread to send callbacks to apps so this app could crash for that reason.\n");
29}
30
31$megaapi = NULL;
32$cwd = NULL;
33
34class AppListener implements MegaListenerInterface
35{
36	public function onRequestStart($megaApi, $request)
37	{
38	}
39
40	public function onRequestFinish($megaApi, $request, $error)
41	{
42		global $cwd;
43
44		if($error->getErrorCode() != MegaError::API_OK)
45		{
46                	print("INFO: Request finished with error ( " . $request . " )   Result: " .  $error . "\n");
47			print("MEGA > ");
48			return;
49		}
50
51		$requestType = $request->getType();
52		if($requestType == MegaRequest::TYPE_LOGIN)
53		{
54			print("Fetchning nodes. Please wait...\n");
55	                print("MEGA > ");
56			$megaApi->fetchNodes();
57		}
58		else if($requestType == MegaRequest::TYPE_FETCH_NODES)
59		{
60                        print("Account correctly loaded\n");
61                        print("MEGA > ");
62			$cwd = $megaApi->getRootNode();
63		}
64		else if($requestType == MegaRequest::TYPE_EXPORT)
65		{
66			print("INFO: Exported link: " . $request->getLink() . "\n");
67			print("MEGA > ");
68		}
69		else if($requestType == MegaRequest::TYPE_ACCOUNT_DETAILS)
70		{
71			$accountDetails = $request->getMegaAccountDetails();
72			print("INFO: Account details received\n");
73			print("Account e-mail: " . $megaApi->getMyEmail() . "\n");
74			print("Storage: " . $accountDetails->getStorageUsed() . " of " . $accountDetails->getStorageMax() .
75				" (" . (100 * $accountDetails->getStorageUsed() / $accountDetails->getStorageMax()) . "%)\n");
76			print("Pro level: " . $accountDetails->getProLevel() . "\n");
77			print("MEGA > ");
78		}
79	}
80
81	public function onRequestTemporaryError($megaApi, $request, $error)
82	{
83		print("INFO: Request temporary error ( " . $request . " )   Error: " + $error . "\n");
84	}
85
86	public function onTransferStart($megaApi, $transfer)
87	{
88		print("INFO: Transfer start ( " . $transfer . " " . $transfer->getFileName() . " )\n");
89	}
90
91	public function onTransferFinish($megaApi, $transfer, $error)
92	{
93		print("INFO: Transfer finished ( " . $transfer . " " . $transfer->getFileName() . " )   Result: " . $error . "\n");
94		print("MEGA > ");
95	}
96
97	public function onTransferUpdate($megaApi, $transfer)
98	{
99		print("INFO: Transfer update ( " . $transfer . " " . $transfer->getFileName() . " )   Progress: " . $transfer->getTransferredBytes()/1024 ." KB of " . $transfer->getTotalBytes()/1024 . " KB, " . $transfer->getSpeed()/1024 . " KB/s\n");
100	}
101
102	public function onTransferTemporaryError($megaApi, $request, $error)
103	{
104		print("INFO: Transfer temporary error ( " . $transfer . " " . $transfer->getFileName() . " )   Error: " . $error . "\n");
105	}
106
107	public function onUsersUpdate($megaApi, $users)
108	{
109	}
110
111	public function onNodesUpdate($megaApi, $nodes)
112	{
113		global $cwd;
114
115		if($nodes != NULL)
116		{
117			print("INFO: Nodes updated ( " . count($nodes) . " )\n");
118			print("MEGA > ");
119		}
120		else
121			$cwd = $megaApi->getRootNode();
122	}
123
124	public function onReloadNeeded($megaApi)
125	{
126
127	}
128}
129
130class LoginCommand extends Command
131{
132    protected function configure()
133    {
134        $this->setName('login');
135        $this->setDescription('Log in to a MEGA account');
136        $this->addArgument('email', InputArgument::REQUIRED, 'Email of the account');
137        $this->addArgument('password', InputArgument::REQUIRED, 'Password of the account');
138    }
139
140    protected function execute(InputInterface $input, OutputInterface $output)
141    {
142		global $megaapi;
143
144        $email = $input->getArgument('email');
145        $password = $input->getArgument('password');
146		$megaapi->login($email, $password);
147    }
148}
149
150class LogoutCommand extends Command
151{
152    protected function configure()
153    {
154        $this->setName('logout');
155        $this->setDescription('Log out a MEGA account');
156    }
157
158    protected function execute(InputInterface $input, OutputInterface $output)
159    {
160		global $megaapi;
161		global $cwd;
162
163		$megaapi->logout();
164		$cwd = null;
165    }
166}
167
168class LsCommand extends Command
169{
170    protected function configure()
171    {
172        $this->setName('ls');
173        $this->setDescription('List a MEGA folder');
174        $this->addArgument('path', InputArgument::OPTIONAL, 'folder path');
175    }
176
177    protected function execute(InputInterface $input, OutputInterface $output)
178    {
179		global $megaapi;
180		global $cwd;
181
182		if($cwd == null)
183		{
184			$output->writeln("Not logged in");
185			return;
186		}
187
188		$path = $input->getArgument('path');
189        if ($path)
190        {
191            $folder = $megaapi->getNodeByPath($path, $cwd);
192        }
193        else
194        {
195            $folder = $cwd;
196        }
197
198
199		$output->writeln("    .");
200		if($megaapi->getParentNode($folder) != NULL)
201		{
202			$output->writeln("    ..");
203		}
204
205		$children = $megaapi->getChildren($folder);
206		foreach($children as $node)
207		{
208			$output->write("    " . $node->getName());
209			if($node->getType() == MegaNode::TYPE_FILE)
210			{
211				$output->writeln("   (" . $node->getSize() . " bytes)");
212			}
213			else
214			{
215				$output->writeln("   (folder)");
216			}
217		}
218    }
219}
220
221class MkdirCommand extends Command
222{
223    protected function configure()
224    {
225        $this->setName('mkdir');
226        $this->setDescription('Create a folder');
227        $this->addArgument('name', InputArgument::REQUIRED, 'folder name');
228    }
229
230    protected function execute(InputInterface $input, OutputInterface $output)
231    {
232		global $megaapi;
233		global $cwd;
234
235		if($cwd == null)
236		{
237			$output->writeln("Not logged in");
238			return;
239		}
240
241		$name = $input->getArgument('name');
242		$megaapi->createFolder($name, $cwd);
243    }
244}
245
246class CdCommand extends Command
247{
248    protected function configure()
249    {
250        $this->setName('cd');
251        $this->setDescription('Change the current directory');
252        $this->addArgument('path', InputArgument::REQUIRED, 'new current directory');
253    }
254
255    protected function execute(InputInterface $input, OutputInterface $output)
256    {
257		global $megaapi;
258		global $cwd;
259
260		if($cwd == null)
261		{
262			$output->writeln("Not logged in");
263			return;
264		}
265
266		$path = $input->getArgument('path');
267		$new = $megaapi->getNodeByPath($path, $cwd);
268		if($new == null)
269		{
270			$output->writeln("Invalid path");
271			return;
272		}
273
274		$cwd = $new;
275    }
276}
277
278class MvCommand extends Command
279{
280    protected function configure()
281    {
282        $this->setName('mv');
283        $this->setDescription('Move a file/folder');
284        $this->addArgument('source', InputArgument::REQUIRED, 'Source file/folder');
285        $this->addArgument('destination', InputArgument::REQUIRED, 'Destination file/folder');
286    }
287
288    protected function execute(InputInterface $input, OutputInterface $output)
289    {
290		global $megaapi;
291		global $cwd;
292
293		if($cwd == null)
294		{
295			$output->writeln("Not logged in");
296			return;
297		}
298
299		$source = $input->getArgument('source');
300		$name = $input->getArgument('destination');
301
302		$srcNode = $megaapi->getNodeByPath($source, $cwd);
303		if($srcNode == null)
304		{
305			$output->writeln($source . ": No such file or directory");
306			return;
307		}
308
309		$dstNode = $megaapi->getNodeByPath($name, $cwd);
310		if(($dstNode != null) && $dstNode->isFile())
311		{
312			$output->writeln($name . ": Not a directory");
313			return;
314		}
315
316		if($dstNode != null)
317		{
318			$megaapi->moveNode($srcNode, $dstNode);
319			return;
320		}
321
322		if(strpos($name,"/") !== false || strpos($name,"\\") !== false)
323		{
324			$str1 = strrchr($name, "/");
325			$str2 = strrchr($name, "\\");
326			$index = null;
327
328			if($str2 == FALSE || strlen($str1) < strlen($str2))
329			{
330				echo "A\n";
331				$index = strlen($name) - strlen($str1);
332			}
333			else
334			{
335				echo "B\n";
336				$index = strlen($name) - strlen($str2);
337			}
338
339			$path = substr($name, 0, $index);
340			$base = $megaapi->getNodeByPath($path, $cwd);
341			$name = substr($name, $index+1);
342
343			echo "INDEX: " . $index . "\n";
344			echo "str1: " . $str1 . "\n";
345			echo "str2: " . $str2 . "\n";
346			echo "PATH: " . $path . "\n";
347			echo "NAME: " . $name . "\n";
348
349			if($base == null)
350			{
351				$output->writeln($path . ": Not such directory");
352				return;
353			}
354
355			if($base->isFile())
356			{
357				$output->writeln($path . ": Not a directory");
358				return;
359			}
360
361			$megaapi->moveNode($srcNode, $base);
362			if(strlen($name) != 0)
363			{
364				$megaapi->renameNode($srcNode, $name);
365			}
366			return;
367		}
368
369		if($dstNode == null)
370		{
371			$megaapi->renameNode($srcNode, $name);
372		}
373    }
374}
375
376class PwdCommand extends Command
377{
378    protected function configure()
379    {
380        $this->setName('pwd');
381        $this->setDescription('Get the current working directory');
382    }
383
384    protected function execute(InputInterface $input, OutputInterface $output)
385    {
386		global $megaapi;
387		global $cwd;
388
389		if($cwd == null)
390		{
391			$output->writeln("Not logged in");
392			return;
393		}
394
395		$output->writeln($megaapi->getNodePath($cwd));
396    }
397}
398
399class RmCommand extends Command
400{
401    protected function configure()
402    {
403        $this->setName('rm');
404        $this->setDescription('Remove a file/folder');
405        $this->addArgument('path', InputArgument::REQUIRED, 'Path to file/folder to delete');
406    }
407
408    protected function execute(InputInterface $input, OutputInterface $output)
409    {
410		global $megaapi;
411		global $cwd;
412
413		if($cwd == null)
414		{
415			$output->writeln("Not logged in");
416			return;
417		}
418
419		$path = $input->getArgument('path');
420		$node = $megaapi->getNodeByPath($path, $cwd);
421		if($node == null)
422		{
423			$output->writeln("Invalid path");
424			return;
425		}
426
427		$megaapi->remove($node);
428    }
429}
430
431class GetCommand extends Command
432{
433    protected function configure()
434    {
435        $this->setName('get');
436        $this->setDescription('Download a file from MEGA');
437        $this->addArgument('path', InputArgument::REQUIRED, 'Path to the file');
438    }
439
440    protected function execute(InputInterface $input, OutputInterface $output)
441    {
442		global $megaapi;
443		global $cwd;
444
445		if($cwd == null)
446		{
447			$output->writeln("Not logged in");
448			return;
449		}
450
451		$path = $input->getArgument('path');
452		$node = $megaapi->getNodeByPath($path, $cwd);
453		if($node == null)
454		{
455			$output->writeln("Invalid path");
456			return;
457		}
458
459		if(!$node->isFile())
460		{
461			$output->writeln("Not a file");
462			return;
463		}
464
465		$megaapi->startDownload($node, "./");
466    }
467}
468
469class PutCommand extends Command
470{
471    protected function configure()
472    {
473        $this->setName('put');
474        $this->setDescription('Upload a file to MEGA');
475        $this->addArgument('path', InputArgument::REQUIRED, 'Path to the local file');
476    }
477
478    protected function execute(InputInterface $input, OutputInterface $output)
479    {
480		global $megaapi;
481		global $cwd;
482
483		if($cwd == null)
484		{
485			$output->writeln("Not logged in");
486			return;
487		}
488
489		$path = $input->getArgument('path');
490		$megaapi->startUpload($path, $cwd);
491    }
492}
493
494class ExportCommand extends Command
495{
496    protected function configure()
497    {
498        $this->setName('export');
499        $this->setDescription('Generate a public link');
500        $this->addArgument('path', InputArgument::REQUIRED, 'Path to the file/folder in MEGA');
501    }
502
503    protected function execute(InputInterface $input, OutputInterface $output)
504    {
505		global $megaapi;
506		global $cwd;
507
508		if($cwd == null)
509		{
510			$output->writeln("Not logged in");
511			return;
512		}
513
514		$path = $input->getArgument('path');
515		$node = $megaapi->getNodeByPath($path, $cwd);
516		if($node == null)
517		{
518			$output->writeln("Invalid path");
519			return;
520		}
521
522		$megaapi->exportNode($node);
523    }
524}
525
526class ImportCommand extends Command
527{
528    protected function configure()
529    {
530        $this->setName('import');
531        $this->setDescription('Import a MEGA public file link');
532        $this->addArgument('link', InputArgument::REQUIRED, 'Public MEGA file link');
533    }
534
535    protected function execute(InputInterface $input, OutputInterface $output)
536    {
537		global $megaapi;
538		global $cwd;
539
540		if($cwd == null)
541		{
542			$output->writeln("Not logged in");
543			return;
544		}
545
546		$link = $input->getArgument('link');
547		$megaapi->importFileLink($link, $cwd);
548    }
549}
550
551class PasswdCommand extends Command
552{
553    protected function configure()
554    {
555        $this->setName('passwd');
556        $this->setDescription('Change the access password');
557        $this->addArgument('current_password', InputArgument::REQUIRED, 'Current password');
558        $this->addArgument('new_password', InputArgument::REQUIRED, 'New password');
559        $this->addArgument('repeat_new_password', InputArgument::REQUIRED, 'New password');
560    }
561
562    protected function execute(InputInterface $input, OutputInterface $output)
563    {
564		global $megaapi;
565		global $cwd;
566
567		if($cwd == null)
568		{
569			$output->writeln("Not logged in");
570			return;
571		}
572
573		$current_password = $input->getArgument('current_password');
574		$new_password = $input->getArgument('new_password');
575		$repeat_new_password = $input->getArgument('repeat_new_password');
576
577		if($new_password != $repeat_new_password)
578		{
579			$output->writeln("Error: Password mismatch");
580			return;
581		}
582
583		$megaapi->changePassword($current_password, $new_password);
584    }
585}
586
587class WhoamiCommand extends Command
588{
589    protected function configure()
590    {
591        $this->setName('whoami');
592        $this->setDescription('Show info about the current user');
593    }
594
595    protected function execute(InputInterface $input, OutputInterface $output)
596    {
597		global $megaapi;
598		global $cwd;
599
600		if($cwd == null)
601		{
602			$output->writeln("Not logged in");
603			return;
604		}
605
606		$output->writeln($megaapi->getMyEmail());
607		$megaapi->getAccountDetails();
608    }
609}
610
611class MountCommand extends Command
612{
613    protected function configure()
614    {
615        $this->setName('mount');
616        $this->setDescription('Show incoming shares');
617    }
618
619    protected function execute(InputInterface $input, OutputInterface $output)
620    {
621		global $megaapi;
622		global $cwd;
623
624		if($cwd == null)
625		{
626			$output->writeln("Not logged in");
627			return;
628		}
629
630		$output->writeln("INFO: INSHARES:");
631		$users = $megaapi->getContacts();
632		foreach($users as $user)
633		{
634			$megaapi->getInShares();
635			$inshares = $megaapi->getInShares($user);
636			foreach($inshares as $share)
637			{
638				$output->writeln("INFO: INSHARE on " . $user->getEmail() . " " . $share->getName() . " Access level: " . $megaapi->getAccess($share));
639			}
640		}
641    }
642}
643
644class ExitCommand extends Command
645{
646    protected function configure()
647    {
648        $this->setName('exit');
649        $this->setDescription('Exit the app');
650    }
651
652    protected function execute(InputInterface $input, OutputInterface $output)
653    {
654		exit(0);
655	}
656}
657
658class QuitCommand extends ExitCommand
659{
660    protected function configure()
661    {
662        $this->setName('quit');
663        $this->setDescription('Exit the app');
664    }
665}
666
667MegaApi::setLogLevel(MegaApi::LOG_LEVEL_ERROR);
668$applistener = new AppListener();
669
670$megaapi = new MegaApiPHP("API_KEY", "PHP megacli");
671$megaapi->addListener($applistener);
672
673$application  = new Application('MEGA', 'PHP');
674$application->add(new LoginCommand());
675$application->add(new LogoutCommand());
676$application->add(new LsCommand());
677$application->add(new MkdirCommand());
678$application->add(new CdCommand());
679$application->add(new PwdCommand());
680$application->add(new RmCommand());
681$application->add(new GetCommand());
682$application->add(new PutCommand());
683$application->add(new ExitCommand());
684$application->add(new QuitCommand());
685$application->add(new ExportCommand());
686$application->add(new ImportCommand());
687$application->add(new WhoamiCommand());
688$application->add(new PasswdCommand());
689$application->add(new MountCommand());
690$application->add(new MvCommand());
691
692$shell = new Shell($application);
693$shell->run();
694
695?>
696
697
698