HEX
Server: Apache
System: Linux webm010.cluster103.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: iestorre (46869)
PHP: 8.0.30
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/iestorre/moodleAW/moodle03/webservice/amf/testclient/AMFTester.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	backgroundColor="white"
	layout="vertical" 
	creationPolicy="all" 
	height="100%" width="100%" 
	applicationComplete="init()"
	xmlns:cv="customValidators.*"
	defaultButton="{call}">

	<mx:Script>
		<![CDATA[
			import mx.rpc.remoting.Operation;
			import mx.rpc.events.ResultEvent;
			import mx.rpc.events.FaultEvent;
			import mx.messaging.Channel;
			import mx.rpc.remoting.RemoteObject;
			import mx.events.ValidationResultEvent;
			import mx.validators.Validator;
			/**
			 * Main class/dialog
			 * 
			 * This program is free software. It comes without any warranty, to
			 * the extent permitted by applicable law. You can redistribute it
			 * and/or modify it under the terms of the Do What The Fuck You Want
			 * To Public License, Version 2, as published by Sam Hocevar. See
			 * http://sam.zoy.org/wtfpl/COPYING for more details.
			 * 
			 * @author Jordi Boggiano <j.boggiano@seld.be>
			 * @author Jamie Pratt <me@jamiep.org>
			 */			
			
			import mx.controls.Label;
			import mx.controls.Alert;
			import mx.messaging.channels.AMFChannel;
			import com.adobe.serialization.json.JSON;
			
 			// Import the debugger
//			import nl.demonsters.debugger.MonsterDebugger;
			
			protected var methods:Array;
			protected var introspector:String;
			
			public var rooturl:String;
			
			[Bindable]
			public var serviceurl:String;
			
			public var channel:AMFChannel;
			
			[Bindable]
			public var argumentToolTip:String = "You can use JSON syntax for method arguments ie. an array is written like this [item1, item2, etc.] objects are written {\"propname\":value, \"propname2\":value2, etc}";
			
			// Variable to hold the debugger
//			private var debugger:MonsterDebugger;

			/**
			 * restores the last settings if available
			 */
			public function init():void
			{
				// Init the debugger
//				debugger = new MonsterDebugger(this);
				
				// Send a simple trace
//				MonsterDebugger.trace(this, "Hello World!");
				
				var so:SharedObject = SharedObject.getLocal('AMFTester');
				if (so.data.token) {
					token.text = so.data.token;
				}
				if (so.data.username) {
					username.text = so.data.username;
					password.text = so.data.password;
				}
				if (so.data.mode == 'username'){
					loginType.selectedIndex = 1;
				}
				this.rememberpassword.selected = so.data.rememberpassword;
				this.remembertoken.selected = so.data.remembertoken;
				this.rooturl = Application.application.parameters.rooturl;
				this.urllabel1.text = 'Root URL :'+this.rooturl;
				this.urllabel2.text = 'Root URL :'+this.rooturl;
				
			}
			public function doConnectToken():void
			{
				serviceurl = this.rooturl + '/webservice/amf/server.php?'+
									'wstoken='+this.token.text;
				this.doConnect();
				// saving settings for next time
				var so:SharedObject = SharedObject.getLocal('AMFTester');
				if (this.rememberpassword.selected == true ){
					so.setProperty('token', this.token.text);
				} else {
					so.setProperty('token', null);//delete shared obj prop
				}
				so.setProperty('remembertoken', this.remembertoken.selected);
				so.setProperty('mode', 'token');
				so.flush();
			}
			public function doConnectUsername():void
			{
				serviceurl = this.rooturl + '/webservice/amf/simpleserver.php?'+
							'wsusername=' + this.username.text+
							'&wspassword=' +  this.password.text;
				this.doConnect();
				// saving settings for next time
				var so:SharedObject = SharedObject.getLocal('AMFTester');
				if (this.rememberpassword.selected == true ){
					so.setProperty('username', this.username.text);
					so.setProperty('password', this.password.text);
				} else {
					so.setProperty('username', null);//delete shared obj prop
					so.setProperty('password', null);
				}
				so.setProperty('rememberpassword', this.rememberpassword.selected);
				so.setProperty('mode', 'username');
				so.flush();
			}
			
			/**
			 * initializes the connection
			 */
			private function doConnect():void
			{
				push("Connecting to "+serviceurl);
				//api.source = 'MethodDescriptor';
				api.setCredentials(this.username.text, this.password.text);
				api.removeEventListener("result", outputResult);
				api.addEventListener("result", handleConnection);
				api.getOperation("MethodDescriptor.getMethods").send();
				if (!api.hasEventListener("fault")) {
					api.addEventListener("fault", faultHandler);
				}
				this.panelDebug.enabled = false;
			}
			
			/**
			 * initializes the debugger dialog with the method list and everything
			 */
			protected function handleConnection(event:ResultEvent):void
			{
				methods = [];
				for (var cls:String in event.result) {
					for (var meth:String in event.result[cls]['methods']) {
						methods.push({label: cls+'.'+meth, docs: event.result[cls]['methods'][meth]['docs'], args: event.result[cls]['methods'][meth]['params']});
					}
				}
				methods.sortOn('label', Array.CASEINSENSITIVE);
				
				this.panelDebug.enabled = true;
				this.maintabs.selectedIndex = 1;
				func.dataProvider = methods;
				api.removeEventListener("result", handleConnection);
				api.addEventListener("result", outputResult);
				reloadArgs();
				
			}
			
			
			/**
			 * outputs a response from the server
			 */
			protected function outputResult(event:ResultEvent):void
			{
				var keys:Array = new Array();
				for (var key:String in event.result){
					keys.push(key);
				}
				push("Result returned \n" + obj2string(event.result));
			}
			
			protected function obj2string(obj:Object, depth:Number=0):String{
				var string:String = '';
				if (obj==null){
					return 'NULL';
				}
				switch (typeof(obj)){
					case 'object':
						if (obj is Array){
							string += "Array\n";
						} else {
							string += "Object\n";
						}
						string += depth2string(depth+1)+"(\n";
						for (var key:String in obj){
							string += depth2string(depth+2)+'['+key+'] => '+obj2string(obj[key], depth+3);
						}
						string += depth2string(depth+1)+")\n";
						break;
					case 'string':
						var formattedstring:String = obj.toString();
						formattedstring = formattedstring.replace(/\r/g, "");
						formattedstring = formattedstring.replace(/\n/g, "\n"+depth2string(depth+3));
						string += '"'+formattedstring+'"'+"-("+typeof(obj)+")"+"\n";
						break;
					default :
						string += obj.toString()+"-("+typeof(obj)+")"+"\n";
				}
				return string;
			}
			
			protected function depth2string(depth:Number):String{
				var string:String = '';
				var i:Number = 0;
				while (i<depth){
					string += '   ';
					i++;
				}
				return string;
			}
			
			/**
			 * updates the display of arguments when the selected method changes
			 * 
			 * it's hardly optimal to do it that way but it was faster to copy paste, I just hope nobody needs more than 7 args
			 */
			protected function reloadArgs():void
			{
				var i:int;
				for (i = 1; i <= 7; i++) {
					this['arg'+i].visible = false;
					this['arg'+i].includeInLayout = false;
					this['larg'+i].visible = false;
					this['larg'+i].includeInLayout = false;
					this['cbarg'+i].visible = false;
					this['cbarg'+i].includeInLayout = false;
					this['JSONV'+i].enabled = false;
				}
				i = 1;
				for (var arg:String in func.selectedItem.args) {
					(this['arg'+i] as TextInput).visible = true;
					(this['arg'+i] as TextInput).includeInLayout = true;
					if (func.selectedItem.args[arg]['required']){
						(this['arg'+i] as TextInput).enabled = true;
						this['cbarg'+i].selected = true;
					}
					(this['larg'+i] as Label).visible = true;
					(this['larg'+i] as Label).includeInLayout = true;
					this['cbarg'+i].visible = !func.selectedItem.args[arg]['required'];
					this['cbarg'+i].includeInLayout = !func.selectedItem.args[arg]['required'];
					this['JSONV'+i].enabled = this['cbarg'+i].selected;
					this['JSONV'+i].required = true;
					
					(this['larg'+i] as Label).text = func.selectedItem.args[arg]['name'] + (func.selectedItem.args[arg]['required'] ? "*":"");
					i++;
				}
				while (i <= 7) {
					this['cbarg'+i].selected = false;
					i++;
				}
				if (func.selectedItem.docs == ""){
					(this.methodDescription as TextArea).text = "";
					(this.methodDescription as TextArea).visible = false;
					(this.methodDescription as TextArea).includeInLayout = false;
				} else {
					(this.methodDescription as TextArea).text = func.selectedItem.docs.replace(/[\n\r\f]+/g, "\n");
					(this.methodDescription as TextArea).visible = true;
					(this.methodDescription as TextArea).includeInLayout = true;
				}
			}
			
			public function toggleCheckBoxes(startAt:uint):void{
				var i:uint= startAt;
				if (this['cbarg'+i].selected){
					i--;
					while (i >= 1){
						this['cbarg'+i].selected = true;
						i--;
					}
				} else {
					i++;
					while (i <= 7){
						this['cbarg'+i].selected = false;
						i++;
					}
				}
			}
			
			/**
			 * calls a method on the server
			 */
			protected function execute():void
			{
				var input:TextInput;
				var argumentArray:Array = [];
				var argumentErrors:Array = Validator.validateAll(argumentValidators);
				if (argumentErrors.length != 0){
//					MonsterDebugger.trace(this, argumentErrors);
					return;
				}
				for(var i:int = 1; i <= 7; i++)
				{
					input = this['arg' +i] as TextInput;
					if(input && input.visible)
					{
						if (!this['cbarg' +i].selected){
							break;
						} else if (input.text.indexOf("\"") == 0 || input.text.indexOf("{") == 0 || input.text.indexOf("[") == 0)
							try {
								argumentArray.push(JSON.decode(input.text));
							} catch (err:Error){
								return;
							}
						else
							argumentArray.push(input.text as String);
					}
				}
				//no other way to pass arguments as array :
				switch (argumentArray.length){
					case 0:
						api.getOperation(func.selectedLabel).send();
						break;
					case 1:
						api.getOperation(func.selectedLabel).send(argumentArray[0]);
						break;
					case 2:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1]);
						break;
					case 3:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1], argumentArray[2]);
						break;
					case 4:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1], argumentArray[2], argumentArray[3]);
						break;
					case 5:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1], argumentArray[2], argumentArray[3], argumentArray[4]);
						break;
					case 6:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1], argumentArray[2], argumentArray[3], argumentArray[4], argumentArray[5]);
						break;
					case 7:
						api.getOperation(func.selectedLabel).send(argumentArray[0], argumentArray[1], argumentArray[2], argumentArray[3], argumentArray[4], argumentArray[5], argumentArray[6]);
						break;
						
				}
				
				
//				MonsterDebugger.trace(this, [func.selectedLabel, argumentArray[0], argumentArray[1], argumentArray[2], argumentArray[3], argumentArray[4], argumentArray[5], argumentArray[6]]);
				push("Calling "+func.selectedLabel+" with arguments \n"+obj2string(argumentArray));
			}
			
			/**
			 * clears debug consoles
			 */
			protected function clear():void
			{
				output.text = output.text = "";
			}
			
			/**
			 * clears debug consoles
			 */
			protected function goBottom():void
			{
				output.verticalScrollPosition = output.maxVerticalScrollPosition;
			}
			
			/**
			 * refreshes the method list
			 */
			protected function refresh():void
			{
				api.removeEventListener("result", outputResult);
				api.addEventListener("result", handleConnection);
				api.exec(introspector);
			}
			
			/**
			 * returns timestamp string
			 */
			protected function time():String
			{
				var d:Date = new Date();
				var ret:String = d.hours+":"+d.minutes+":"+d.seconds+"."+d.milliseconds;
				return ret + "000000000000".substring(ret.length);
			}

			/**
			 * handler for specific net events
			 */
			public function faultHandler(event:FaultEvent):void 
			{
				push("Error("+event.type+" - "+ event.fault.faultCode + "): "+event.fault.faultString+", "+event.fault.faultDetail);
			}
			

			
			/**
			 * pushes text into a console and scrolls it down automatically
			 */
			public function push(text:String):void
			{
				output.text += time() + ": "+ text + "\n";
				output.verticalScrollPosition = output.maxVerticalScrollPosition;
			}

		]]>
	</mx:Script>
	<mx:RemoteObject id="api" destination="zend" endpoint="{serviceurl}" />

	<mx:Array id="argumentValidators">
		<cv:JSONValidator id="JSONV1" required="true" enabled="{cbarg1.selected}" source="{arg1}"  property="text" />
		<cv:JSONValidator id="JSONV2" required="true" enabled="{cbarg2.selected}" source="{arg2}"  property="text" />
		<cv:JSONValidator id="JSONV3" required="true" enabled="{cbarg3.selected}" source="{arg3}"  property="text" />
		<cv:JSONValidator id="JSONV4" required="true" enabled="{cbarg4.selected}" source="{arg4}"  property="text" />
		<cv:JSONValidator id="JSONV5" required="true" enabled="{cbarg5.selected}" source="{arg5}"  property="text" />
		<cv:JSONValidator id="JSONV6" required="true" enabled="{cbarg6.selected}" source="{arg6}"  property="text" />
		<cv:JSONValidator id="JSONV7" required="true" enabled="{cbarg7.selected}" source="{arg7}"  property="text" />
	</mx:Array>
		

	
	<mx:HBox width="100%" height="550">
	    <mx:TabNavigator id="maintabs" height="100%" width="100%" >
	    	
		    <mx:TabNavigator label="Connect" id="loginType" borderStyle="solid" height="100%" width="100%">
				<mx:Panel label="Use Token" id="panelConnectToken">
					<mx:HBox width="100%">
						<mx:Label text="Token"/>
						<mx:TextInput id="token" text=""  width="100%"/>
					</mx:HBox>
					<mx:HBox width="100%">
						<mx:Label text="Remember"/>
						<mx:CheckBox id="remembertoken" width="100%"/>
					</mx:HBox>
					<mx:Label id="urllabel1" text="URL :" />
					<mx:HBox width="100%">
						<mx:Spacer width="100%" />
						<mx:Button label="Connect" click="doConnectToken()"/>
						<mx:Spacer width="100%" />
					</mx:HBox>
				</mx:Panel>
				<mx:Panel label="Use Username and Password" id="panelConnectUsername">
					<mx:HBox width="100%">
						<mx:Label text="Username"/>
						<mx:TextInput id="username" text=""  width="100%"/>
					</mx:HBox>
			
					<mx:HBox width="100%">
						<mx:Label text="Password"/>
						<mx:TextInput id="password" text="" displayAsPassword="true"  width="100%"/>
					</mx:HBox>
					<mx:HBox width="100%">
						<mx:Label text="Remember"/>
						<mx:CheckBox id="rememberpassword" width="100%"/>
					</mx:HBox>
					<mx:Label id="urllabel2" text="URL :" />
			
					<mx:HBox width="100%">
						<mx:Spacer width="100%" />
						<mx:Button label="Connect" click="doConnectUsername()"/>
						<mx:Spacer width="100%" />
					</mx:HBox>
				</mx:Panel>
			</mx:TabNavigator>
			<mx:Panel label="Service Browser" width="100%" height="100%" layout="vertical" title="Moodle AMF Service Browser" enabled="false" id="panelDebug">
				<mx:HBox width="100%">
					<mx:Label text="Func "/>
					<mx:ComboBox id="func" change="reloadArgs()">
					</mx:ComboBox>
				</mx:HBox>
				<mx:TextArea id="methodDescription" text="" width="100%" height="150"/>
				<mx:HBox width="100%">
					<mx:Label id="larg1" text="Arg 1"/>
					<mx:CheckBox id="cbarg1" click="toggleCheckBoxes(1)"/>
					<mx:TextInput id="arg1" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg1.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg2" text="Arg 2"/>
					<mx:CheckBox id="cbarg2" click="toggleCheckBoxes(2)"/>
					<mx:TextInput id="arg2" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg2.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg3" text="Arg 3"/>
					<mx:CheckBox id="cbarg3" click="toggleCheckBoxes(3)"/>
					<mx:TextInput id="arg3" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg3.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg4" text="Arg 4"/>
					<mx:CheckBox id="cbarg4" click="toggleCheckBoxes(4)"/>
					<mx:TextInput id="arg4" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg4.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg5" text="Arg 5"/>
					<mx:CheckBox id="cbarg5" click="toggleCheckBoxes(5)"/>
					<mx:TextInput id="arg5" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg5.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg6" text="Arg 6"/>
					<mx:CheckBox id="cbarg6" click="toggleCheckBoxes(6)"/>
					<mx:TextInput id="arg6" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg6.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Label id="larg7" text="Arg 7"/>
					<mx:CheckBox id="cbarg7" click="toggleCheckBoxes(7)"/>
					<mx:TextInput id="arg7" toolTip="{argumentToolTip}" width="100%" enabled="{cbarg7.selected}"/>
				</mx:HBox>
				<mx:HBox width="100%">
					<mx:Button id="call" label="Call" click="execute()"/>
					<mx:Button label="Clear" click="clear()"/>
					<mx:Button label="Scroll to bottom of debug output" click="goBottom()"/>				
				</mx:HBox>
			</mx:Panel>
	    </mx:TabNavigator>
	</mx:HBox>
	<mx:HBox width="100%" height="100%">
		<mx:TextArea id="output"  width="100%" height="100%"/>
	</mx:HBox>
</mx:Application>