Index: files/externallib.php
===================================================================
RCS file: files/externallib.php
diff -N files/externallib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/externallib.php	8 Dec 2009 06:31:11 -0000
@@ -0,0 +1,297 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * External files API
+ *
+ * @package    moodlecore
+ * @subpackage webservice
+ * @copyright  2009 Dongsheng Cai <dongsheng@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("$CFG->libdir/externallib.php");
+require_once("$CFG->libdir/filelib.php");
+
+class moodle_file_external extends external_api {
+
+    /**
+     * Returns description of get_files parameters
+     * @return external_function_parameters
+     */
+    public static function get_files_parameters() {
+        return new external_function_parameters(
+            array(
+                'params' => new external_single_structure(array(
+                        'contextid' => new external_value(PARAM_INT, 'context id'),
+                        'itemid'    => new external_value(PARAM_INT, 'associated id'),
+                        'filearea'  => new external_value(PARAM_TEXT, 'file area'),
+                        'filepath'  => new external_value(PARAM_RAW, 'file path'),
+                        'filename'  => new external_value(PARAM_TEXT, 'file name'),
+                    )
+                )
+            )
+        );
+    }
+
+    /**
+     * Return moodle files listing
+     * @param array $fileinfo
+     * @return array
+     */
+    public static function get_files($fileinfo) {
+        global $CFG, $USER, $OUTPUT;
+        if (empty($fileinfo['itemid'])) {
+            $fileinfo['itemid'] = null;
+        }
+        if (empty($fileinfo['filename'])) {
+            $fileinfo['filename'] = null;
+        }
+        if (empty($fileinfo['filepath'])) {
+            $fileinfo['filepath'] = null;
+        }
+        if (empty($fileinfo['filearea'])) {
+            $fileinfo['filearea'] = null;
+        }
+        if (empty($fileinfo['contextid'])) {
+            $context  = get_system_context();
+        } else {
+            $context  = get_context_instance_by_id($fileinfo['contextid']);
+        }
+        try {
+            $browser = get_file_browser();
+
+            $ret = array();
+            $ret['parents'] = array();
+            $ret['files'] = array();
+            $file = $browser->get_file_info($context, null, null, null, null);
+            if ($file = $browser->get_file_info($context, $fileinfo['filearea'], $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename'])) {
+                $level = $file->get_parent();
+                while ($level) {
+                    $params = $level->get_params();
+                    $params['filename'] = $level->get_visible_name();
+                    array_unshift($ret['parents'], $params);
+                    $level = $level->get_parent();
+                }
+                $list = array();
+                $children = $file->get_children();
+                foreach ($children as $child) {
+                    $params = $child->get_params();
+                    if ($child->is_directory()) {
+                        $node = array(
+                            'filename' => $child->get_visible_name(),
+                            'filepath' => $params['filepath'],
+                            'filearea' => $params['filearea'],
+                            'itemid' => $params['itemid'],
+                            'contextid' => $params['contextid'],
+                            'url' => null,
+                            'isdir'=>true
+                        );
+                        $list[] = $node;
+                    } else {
+                        $node = array(
+                            'filename' => $child->get_visible_name(),
+                            'filepath' => $params['filepath'],
+                            'filearea' => $params['filearea'],
+                            'itemid' => $params['itemid'],
+                            'contextid' => $params['contextid'],
+                            'url' => $child->get_url(),
+                            'isdir'=>false
+                        );
+                        $list[] = $node;
+                    }
+                }
+            }
+            $ret['files'] = $list;
+        } catch (Exception $e) {
+            throw $e;
+        }
+        return $ret;
+    }
+
+    /**
+     * Returns description of get_files returns
+     * @return external_multiple_structure
+     */
+    public static function get_files_returns() {
+        return new external_multiple_structure(
+            new external_single_structure(
+                array(
+                    'parents' => new external_multiple_structure(new external_single_structure(array(
+                            new external_single_structure(
+                                array(
+                                    'contextid' => new external_value(PARAM_INT, ''),
+                                    'filename' => new external_value(PARAM_TEXT, ''),
+                                    'filearea' => new external_value(PARAM_TEXT, ''),
+                                    'filepath' => new external_value(PARAM_TEXT, ''),
+                                    'itemid'   => new external_value(PARAM_INT, '')
+                                    )
+                                )
+                        ))),
+                    'files' => new external_multiple_structure(new external_single_structure(array(
+                            new external_single_structure(
+                                array(
+                                    'filename' => new external_value(PARAM_TEXT, ''),
+                                    'filearea' => new external_value(PARAM_TEXT, ''),
+                                    'filepath' => new external_value(PARAM_TEXT, ''),
+                                    'itemid'   => new external_value(PARAM_INT, ''),
+                                    'isdir'    => new external_value(PARAM_BOOL, ''),
+                                    'url'      => new external_value(PARAM_TEXT, ''),
+                                    'contextid' => new external_value(PARAM_INT, '')
+                                    )
+                                )
+                        ))) 
+                )
+            )
+        );
+    }
+
+    /**
+     * Returns description of upload parameters
+     * @return external_function_parameters
+     */
+    public static function upload_parameters() {
+        return new external_function_parameters(
+            array(
+                'params' => new external_single_structure(array(
+                        'contextid' => new external_value(PARAM_INT, 'context id'),
+                        'itemid'    => new external_value(PARAM_INT, 'associated id'),
+                        'filearea'  => new external_value(PARAM_TEXT, 'file area'),
+                        'filepath'  => new external_value(PARAM_RAW, 'file path'),
+                        'filename'  => new external_value(PARAM_TEXT, 'file name'),
+                        'filecontent' => new external_value(PARAM_TEXT, 'file content')
+                    )
+                )
+            )
+        );
+    }
+
+    /**
+     * Uploading a file to moodle
+     *
+     * @param array $fileinfo
+     * @return array
+     */
+    public static function upload($fileinfo) {
+        global $USER, $CFG;
+
+        if (!isset($fileinfo['filecontent'])) {
+            throw new moodle_exception('nofile');
+        }
+        // saving file
+        if (!file_exists($CFG->dataroot.'/temp/wsupload')) {
+            mkdir($CFG->dataroot.'/temp/wsupload/', 0777, true);
+        }
+
+        if (is_dir($CFG->dataroot.'/temp/wsupload')) {
+            $dir = $CFG->dataroot.'/temp/wsupload/';
+        }
+
+        if (empty($fileinfo['filename'])) {
+            $filename = uniqid('wsupload').'_'.time().'.tmp';
+        } else {
+            $filename = $fileinfo['filename'];
+        }
+
+        if (file_exists($dir.$filename)) {
+            $filename = uniqid('m').$filename;
+        }
+
+        $savedfilepath = $dir.$filename;
+
+        file_put_contents($savedfilepath, base64_decode($fileinfo['filecontent']));
+        unset($fileinfo['filecontent']);
+
+        if (!empty($fileinfo['filearea'])) {
+            $filearea = $fileinfo['filearea'];
+        } else {
+            $filearea = null;
+        }
+
+        if (!empty($fileinfo['filepath'])) {
+            $filepath = $fileinfo['filepath'];
+        } else {
+            $filepath = '';
+        }
+ 
+        if (!empty($fileinfo['itemid'])) {
+            $itemid = $fileinfo['itemid'];
+        } else {
+            $itemid = (int)substr(hexdec(uniqid()), 0, 9)+rand(1,100);
+        }
+        if (!empty($fileinfo['contextid'])) {
+            $context = get_context_instance_by_id($fileinfo['contextid']);
+        } else {
+            $context = get_system_context();
+        }
+
+        $fs = get_file_storage();
+        $browser = get_file_browser();
+
+        // check existing file
+        if ($file = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
+            throw new moodle_exception('fileexist');
+        }
+
+        $file_record = new object();
+        $file_record->contextid = $context->id;
+        $file_record->filearea  = $filearea;
+        $file_record->itemid    = $itemid;
+        $file_record->filepath  = $filepath;
+        $file_record->filename  = $filename;
+        $file_record->userid    = $USER->id;
+
+        // move file to filepool
+        try {
+            $file = $fs->create_file_from_pathname($file_record, $savedfilepath);
+            unlink($savedfilepath);
+        } catch (Exception $ex) {
+            throw $ex;
+        }
+        $info = $browser->get_file_info($context, $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $file->get_filename());
+
+        return array(
+            'filename'=>$file->get_filename(),
+            'filepath'=>$file->get_filepath(),
+            'filearea'=>$file->get_filearea(),
+            'url'=>$info->get_url()
+            );
+    }
+
+    /**
+     * Returns description of upload returns
+     * @return external_multiple_structure
+     */
+    public static function upload_returns() {
+        return new external_multiple_structure(
+            new external_single_structure(
+                array(
+                    'fileinfo' => new external_single_structure(
+                            array(
+                                'filename' => new external_value(PARAM_TEXT, ''),
+                                'filepath' => new external_value(PARAM_TEXT, ''),
+                                'filearea' => new external_value(PARAM_TEXT, ''),
+                                'url' => new external_value(PARAM_TEXT, ''),
+                            )
+                    )
+                )
+            )
+        );
+    }
+
+}
+
Index: lib/db/services.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/services.php,v
retrieving revision 1.11
diff -u -r1.11 services.php
--- lib/db/services.php	5 Nov 2009 22:06:49 -0000	1.11
+++ lib/db/services.php	8 Dec 2009 06:31:11 -0000
@@ -83,6 +83,20 @@
         'description' => 'Deletes group members.',
         'type'        => 'delete',
     ),
+    'moodle_file_get_files' => array(
+        'classname'   => 'moodle_file_external',
+        'methodname'  => 'get_files',
+        'description' => 'browse moodle files',
+        'type'        => 'read',
+        'classpath'   => 'files/externallib.php',
+    ),
+    'moodle_file_upload' => array(
+        'classname'   => 'moodle_file_external',
+        'methodname'  => 'upload',
+        'description' => 'upload a file to moodle',
+        'type'        => 'write',
+        'classpath'   => 'files/externallib.php',
+    ),
 
     // === user related functions ===
 /*
Index: version.php
===================================================================
RCS file: /cvsroot/moodle/moodle/version.php,v
retrieving revision 1.1351
diff -u -r1.1351 version.php
--- version.php	7 Dec 2009 00:32:31 -0000	1.1351
+++ version.php	8 Dec 2009 06:31:11 -0000
@@ -6,7 +6,7 @@
 // This is compared against the values stored in the database to determine
 // whether upgrades should be performed (see lib/db/*.php)
 
-    $version = 2009112400;  // YYYYMMDD   = date of the last version bump
+    $version = 2009112404;  // YYYYMMDD   = date of the last version bump
                             //         XX = daily increments
 
     $release = '2.0 dev (Build: 20091207)';  // Human-friendly version name
