Quick Start

Last updated: Sep 18th, 2018

Installation

Step One

This section will cover the complete installation of marble including installing functionality to allow you to run marble in your terminal. You first need to ensure that you have apache2 installed if you do not install the apache2 webserver first. If you do not want to install for apache skip the final command "sudo apt-get install marble-apache2" and skip anything relating to apache in this installation

Open your terminal and enter the commands below to install marble. 

Default code example:

sudo add-apt-repository ppa:nibblebits/marble

sudo apt-get update

sudo apt-get install marble-core

sudo apt-get install marble-cli

sudo apt-get install marble-apache2

Step Two

Great you now have marble installed congratulations! 
There is one more step we have to take for apache and that is to define a directory on the web server that marble files can be run in. This is done by modifying your apache configuration.

Open your apache configuration and we can begin

sudo nano /etc/apache2/apache2.conf

Now your going to need to paste the XML below into your apache2 configuration and modify it appropriately. It does not matter where you paste it but we recommend finding an appropriate place to keep your configuration clean.

Apache2 Marble Configuration
<Location />
 SetHandler marble
 ConfigLocation "/etc/marble/webconfig.marble"
</Location>

The above configuration says that all files in the root directory and sub directories of your web space should allow for marble support if a marble file is run. The ConfigLocation is the location of the web configuration file for Marble. All configuration files for Marble are written in Marble its self. Please read the section on configuration to learn more.

Step Three

Save the apache configuration file and all that is left to do is restart your apache server which can be done with the command below.

sudo service apache2 restart

Starters Guide

Great so you have succesfully installed and setup marble. Throughout the rest of this quick start guide all examples can be run in the terminal or on your apache2 web server. You wil learn all the basics in Marble to get a feel for the language and once your done you can progress through the other learning sections located at the home page. Let's now create your very first program a simple marble script that outputs "Hello World!"

Useful Tip:

You can view our full class and function reference API here

My first program

Create a new directory  in /var/www/html and we will call it marble. We will test our examples here.
Once you have done that create a file called index.marble so the full path will be /var/www/html/marble/index.marble.
Open the file you have just created and paste the following code

<marble>
print("Hello World!");
</marble>

Now save the file and navigate in your web browser to "http://127.0.0.1/marble/index.marble" if you have done this correctly you should see a message that says "Hello World!". You can also run this program in the terminal with the following command 

marble /var/www/html/marble/index.marble

In Marble there are many ways to do the same thing this is by design to allow preference for example you can also output data in the following other two ways.

Other ways of printing
<marble>
IO.print("Hello World!");
</marble>
<marble>
"Hello World!";
</marble>
Mixing HTML and Marble

HTML can be easily mixed with Marble below shows a code example of how to do this

<html>
<head>
<title><marble>print("A nice title from marble");</marble></title>
</head>
<body>
<marble>print("Marble has a body");</marble>
</body>
</html>
Variables

Marble is an OOP(Object Oriented Language). Marble has a few primitive datatypes

Primitive Datatypes in Marble
  • number - Represents a double type
  • string - Represents a string type
  • boolean - Represents a boolean type and can equal true or false
  • int - Represents an integer (this is a castable only type you cannot declare this on its own you can only cast to it)

Creating variables in marble is easy as shown below

Variable Creation
<marble>
# This is a comment. Comments in marble start with a hash tag
# anything with a hash tag is not run by Marble and is used only to document your code

# Variable examples
number x = 30.25;
string y = "Hello world";
boolean z = true;

# Printing these variables
# Converts variable x to a string and then prints it. 30.25 is outputted
print((string) x);
# Prints "Hello World" as variable y holds this value
print(y);
# Converts the value of variable z to a string and then prints 1 as variable z is true
print((string) z);
</marble>
Array variables
<marble>
# Array variable examples
number[] x = new number[20];
x[0] = 10;
x[1] = 20;
# Printing these variables
print((string) x[0]);
print((string) x[1]);
</marble>

Arrays are very easy to create in Marble

Casting Basics

Casting in Marble is similar to how you cast in many other popular programming languages. Below is an example of casting a double to an integer causing it to lose its floating point value.

<marble>
 number x = 23.20;
 number y = (int) x;
 # Variable x holds 23.20
 # Variable y now holds 23
</marble>
Statements and conditions

Statements allow you to express yourself in your code and change the flow of execution throughout your program. Marble supports four types of statements 

  • If statements
  • For statements
  • While statements
  • Do while statements

If statements allow you to make certain things happen if a certain criteria is met within your program. Take the below example. This example will print the word "fifty" if the number "x" is equal to 50.

<marble>
   number x = 50;
   if (x == 50)
   {
      print("Fifty");
   }
</marble>

There will certainly be a time where you will also want a condition where it will do something if the variable is equal to something but do something else if it is not equal to something. You can do this by adding an else keyword take the following example

<marble>
   number x = 50;
   if (x == 50)
   {
      print("Fifty");
   }
  else
  {
      print("Not fifty");
  }
</marble>

You may also want to use check if a condition is equal to 50 and if its not check if its equal to 40 and if its not 50 or 40 do something else. You can do this in marble easily by appending your if statements accordingly. Take the below example

<marble>
   number x = 50;
   if (x == 50)
   {
      print("Fifty");
   }
  else if(x == 40)
  {
      print("Forty");
  }
  else
  {
     print("Not fifty or forty");
  }
</marble>
While statements example

When you program there are times where you need to repeat the same action multiple of times in marble there are three ways to do this the first way is to use while statements, the second way is to use do while statements and finally the third way is to use for statements. We will first discuss while statements which can be seen below

<marble>
number x = 0;
while(x <= 10)
{
     # Repeat this when x is below or equal to ten
     print("Hello world"); # Hello world is printed 11 times 
     x += 1;
}
</marble>

So the code above first creates a variable named x after this we enter a while statement at this point in time your computer will check if variable x is below or equal to ten if it is then it will run the code between these two braces {} this code will keep running until the result of the condition in the while statement is zero or false so in our example if variable x is below or equal to ten then a true is returned otherwise a false is returned. If the while statement gets a false it will no longer run the code between the braces. The action of this code running between those braces is called a loop as the code between the braces can be run multiple of times based on certain conditions.

Do while statements example
<marble>
number x = 0;
do
{
     # This code block is run only once as x is below 5
     # If this was a normal while loop this code in this code block would never be run as x is below 5
     print("Hello world");
     x += 1;
}
while(x >= 5);
</marble>

Do while statements are very simular to while statements the only difference is that it runs the code in between the braces first before checking a condition and then checks a condition after its run the code in between the braces. If the result of that condition is false then the loop will not be run again. If the result is true then the loop will be run again. Above is an example of do while statements.

For statement example
<marble>
for (number x = 0; x < 10; x +=1)
{
    # \n Means to create a new line if this example is run in the terminal you will see the values printed line by line
    print("Value: " + ((string) x) + "\n");
}

# OUTPUTS
# Value: 0
# Value: 1
# Value: 2
# Value: 3
# and so on
</marble>

For statements also known as  for loops are a special type of statement they allow you to declare a variable, check a condition and adjust a variable value all in one statement. For loops are very useful for times that require counting such as a loop that will count up to ten. Above is an example of a for statement. 

You can leave any loop early by issuing a " break;" within your code. If you want to stay in the loop but loop back around then use " continue;" and if the expression then evaluates to true again then the loop will be run again from the top.

Functions

A function is a group of statements that together perform a task. Functions can be defined and called throughout your program and are ideal for organising and splitting up your code into a neat and tidy way. Functions have names, arguments and can return values. Function arguments are variables that hold values that you pass to a function. Below shows how to create a function in Marble and call it.

Function creation
<marble>
function myFunction(string arg1, number arg2) : void
{
   for (number i = 0; i < arg2; i+=1)
   {
        print(arg1);
   }
}

# Print hello world 10 times
myFunction("Hello world!\n", 10);
</marble>

In the code above we create a function called "myFunction" that takes two arguments the first argument being a string and the second argument being a number. We then call this function and pass "Hello world!\n" for the first argument and 10 for the second argument. Our function is designed to  print out a provided message a given number of times and that is exactly what it does. "Hello world!\n" is printed 10 times. If you see where we have declared the function the void at the end is the return type a return type of void means that we will not return any values to our function caller

Function example that returns a string
<marble>
function myFunction(string arg1, number arg2) : string
{
   for (number i = 0; i < arg2; i+=1)
   {
        print(arg1);
   }
   return "My return message";
}

# Print hello world 10 times
string message = myFunction("Hello world!\n", 10);
print(message);
</marble>

Take a look at the code above this time we have changed our function to return a string. It returns "My return message" to any caller that calls it. You can see we have replaced void with string  this simply means we wish to return a string. We then use the return keyword to return a string. We then call myFunction and store what it returns into a variable named  message and then print that variable out. Functions can have no arguments () or even just one (string arg1)

In the next chapter we will talk about objects but before we do you must know that when passing an object to a function if the function accepts a base class of the child class object you are passing to it you will have to cast it. For example if you have a function called "testing" that accepts an argument that takes an "Object" you will need to cast your object you are passing to it for it to be valid. "testing((Object) my_obj);"

Object Orientation In Marble 

Marble is an OOP(Object Oriented Programming) language therefore marble supports the creation of classes and supports abstraction. To create an abstract class in Marble you only have to define the class as " pure". Pure in marble means the same as abstract means in other languages such as Java.

Marble class declaration example
<marble>
class MyClassName extends MyOtherClass
{
public:
   function __construct() : void
   {
       # My marble constructor
   }
   
   function doSomething() : void
   {
      print("doSomething() called");
   }
   # Public variable called x
   number x;
private:
   # Private variable called y
   number y;

protected:
   # Protected variable called z
   number z;
}
</marble>

All marble classes start with a class keyword unless they are pure in which case they start with " pure class". All Marble classes must have a constructor and this constructor is simply a function named " __construct" that returns void. Anything declared under " public:" will be able to be accessed by anything inside or outside of the class. Anything declared under " private:" will only be accessible from the class its self. Finally anything declared under " protected:" will only be accessible from the current class and its children(Other classes that extend from it).

If you are creating a class that extends nothing you can simply define the class as either " class MyClassName" or " class MyClassName extends Object"

Pure Class Example
<marble>
# Below we define a pure abstract class called MyBaseClass
pure class MyBaseClass
{
public:
   function __construct() : void
   {
       # My marble constructor
   }
   
   # We define a pure abstract function that has no body as its to be implemented by its children
   pure function functionToOverride() : void;

   function doSomething() : void
   {
      print("doSomething() called");
   }
   # Public variable called x
   number x;
private:
   # Private variable called y
   number y;

protected:
   # Protected variable called z
   number z;
}

class MyChildClass extends MyBaseClass
{

   function __construct() : void
   {
       # My marble constructor
   }
   
  # Overrided "functionToOverride" from "MyBaseClass"
  function functionToOverride() : void
  {
     print("Happy Days");
  }
}

</marble>

Pure classes in Marble allow you to define signatures of functions you are basically saying I have this function named " functionToOverride" I don't know what I want it to do so just keep it here until someone else can implement it for me. A child class can then extend this pure class of yours and implement the pure  function. Now any call to the pure function on the Object instance will lead to the function being called in the child class.

Below illiterates how you can create a new instance of your class

MyBaseClass cls = new MyChildClass();
cls.functionToOverride();

Whilst inside a class method/function to access things in that class you must use "this". For example "this.doSomething();" or "this.x = 50;". To access something in the super class use "super". "super.doSomething();"

If you are lost please research about Object Oriented Programming as this OOP guide is designed to teach OOP in Marble not the underlying principles themselves.

Exception Handling

Exceptions in Marble are a way of telling the program something is wrong and then either recovering from it or failing. Let's create an exception and throw it to say something is wrong

Exception creation
<marble>

# Here we create our own exception that extends Exception
# all exception classes must extend Exception
# We pass the string provided to the super class which is Exception
# this string we are passing is the exception message
class MyCustomException extends Exception
{
public:
    function __construct(string s) : void
    {
        super.__construct(s);
    }
    
}




# Let's throw a new exception
try
{
    throw new MyCustomException("Failed");
}
catch(MyCustomException ex)
{
    # Here we catch the Exception
    print("Caught: " + ex.getMessage() + "\n");
    print(ex.getStackTrace() + "\n");
}
</marble>

So in the above code we create an exception class of our own and them throw it with a message and catch it. If we fail to catch it the system will catch it for us and terminate the program.

Including Files

Chances are you are not going to want your entire program to be in one file things can get messy this way. Marble has support for including other files at run time. These files could be anything from project configuration to files with functions in. In this section we will demonstrate how to include files and important things you must know about doing so.

There are two different types of file includes in Marble. There is your standard include which can be used without knowing the file you want to load before run time. The filename of a file you want to load could be stored in a variable and then you can include the file with the variables value which will hold the filename. This type of include is great if you have a project that supports plugins. You can then load those plugins in this way.

The second way to include files in Marble is called requiring. You require a file if you already know the file path before run time these types of includes are great for loading configuration and project dependencies.

Let's first discuss requiring as its the easiest of the two.    

Requiring Files Example

So for this example we will have two files "main.marble" and "config.marble" our main script is "main.marble" and "config.marble" contains configuration settings that we want to load.

config.marble - File

<marble>
# Project Config File

# Database information
string host = "...";
string username = "...";
string password = "...";
string database = "...";

function getDatabaseHost() : string
{
    return host;
}

function getDatabaseUsername() : string
{
    return username;
}

function getDatabasePassword() : string
{
    return password;
}

function getDatabaseName() : string
{
    return database;
}


</marble>

The above file named " config.marble" contains database information along with some functions to get that information in a tidy way. Now below " main.marble" illustrates how to load this file and access this information

main.marble - File

<marble>
# We require the file config.marble causing it to become a part of our source code
require "config.marble";

# Let's output the database host
print(host);
# And again through the function
print(getDatabaseHost());
</marble>

So you can see above we require the file "config.marble" what happens here is Marble sees you have required it and it loads the file and merges it with your main file causing it to appear like they are one file. This allows you to access everything in "config.marble" very easily.

Requiring files requires that you know the real file path before run time. Let's now take a look at how you can include files at run time without knowing the file path until the moment you include it.

Including Files Example

file.marble - File

<marble>
function doSomething() : void
{
    print ("hello world");
}
</marble>

main.marble - File

<marble>
string filename = "./file.marble";
# Include file.marble
include filename;

# To call the function inside you use @ first this says to ignore validation
@doSomething();

</marble>

We first run main.marble this then includes " file.marble". Now because include does not require that you know the filename before run time this means that the file you include does not get validated the same time as the file you have just run " main.marble". This means that after you have included " file.marble" although functions have been loaded correctly your main script cannot see them. Simply calling " doSomething()" will result in the system complaining that the function does not exist. To get around this marble has a validation supression operator " @". If you put the " @" operator in front of a function it tells Marble to ignore validation for this function call and instead validate it just before it calls the function and not when the script is first loaded. Using this operator will then allow you to call functions that do or do not exist. If the function does not exist an exception is thrown.

Things to know about including files with the "include" keyword

When including files with the " include" keyword it does not merge your code with the main script like it does with " require" what happens instead is a brand new scope is created before your file is included this means any variables you declare in a script included with the " include" keyword results in a fresh scope meaning that after your " include" statement has completed you have no access to the global scope of the file you have included. This however does mean their are rules to follow when using the " include" keyword firstly know that if you create any functions within a script you include with " include" those functions cannot return any variables in the global scope of the include file. Doing so will result in the system complaining that the variable could not be found. We will demonstrate this now to get this out of the way so you are aware of this problem. I will provide two examples one that shows the problem and one that shows what is allowed.

Illegal Scope for Included Files

file.marble - File

<marble>
string mystring = "hello world";

function myFunction() : string
{
    return mystring;
}
</marble>

main.marble - File

<marble>
include "file.marble";
string s = @myFunction();
print(s);
</marble>

You will see an error if you run the above code this is expected due to the file having a seperate scope when loaded with " include" you do not have this problem if you include a file with " require". There are many ways to communicate with the files correctly and get around this problem. Files included with " include" can have their functions accessed correctly from outside the file so long as the file you are including is not accessing its global variables in the function you are calling. One way around this problem is to define classes within the files you include and do your functionality in there you can then return the object to the caller and there will be no problems.

Below is an example showing legal communication between files included with " include"

Legal Communication for Include Files

file.marble - File

<marble>

class MyCoolClass extends MyMainClass
{
public:
    function __construct(string message) : void
    {
       # We can call methods above us with "super"
       super.__construct();
       this.message = message;    
    }

    function getMessage() : string
    {
        return this.message;
    }
    
private:
    string message;
}


MyCoolClass cls = new MyCoolClass("Hello world!");
return_value.set((Object) cls);

</marble>

main.marble - File

<marble>
class MyMainClass
{
public:
    function __construct() : void
    {
    
    }
}

# We need to create a Value object called return_value so our "plugin" can return something to us
# The Value class in marble can hold any value let's try it out
Value return_value = new Value();
# Include the file
include "file.marble";

# Let's now get the object from the file we included but we want to declare it to ignore validation for the whole class
# as we are going to call methods that are not part of the super class
# and we can imagine we don't know the class name of the class our plugin has created
@MyMainClass cls = (MyMainClass) return_value.getObject();
# Let's get the message. Notice how we do not need to provide "@" to the getMessage() function this is because
# we told Marble to ignore validation for all operations on the "cls" variable above ^^^
string message = cls.getMessage();
print(message);
</marble>

So whats going on here? Well let's pretend this is our imaginary plugin system we have created a class named " MyMainClass" this class is to be extended by all of our plugins and we will use it to access our plugins correctly.

We create a variable of type Value named return_value. Value in marble is a class that can hold any value. This variable we have just created will be seen by our imaginary plugin that we include and it access this object as it is defined before the plugin is included. Files we include can access our scopes we just can't access theres. Inside " file.marble" we create a class named " MyCoolClass" this extends our " MyMainClass" class we defined in the main file. The " MyCoolClass" class takes a string for its first argument in its constructor this is a message we want to pass back to the file that included us. We have a function in the " MyCoolClass" class that returns the message that was set when called. 

Inside our plugin " file.marble" we then create a new instance of " MyCoolClass" and set our return value object declared in "main.marble" to the value of the " MyCoolClass" object we have just created.

Back at " main.marble" we can now get the object from " return_value" giving us access to the " MyCoolClass" object instance that was created. You will notice we then suppress validation on the " cls" variable you can read more about this in the code comments.

Filtering And Capturing Output

There comes a time where you need to be able to filter output within Marble one reason is to strip html outputted from plugins in your system. Another reason would be to load a view file that you plan to email to someone, you can include it and capture the output and send it straight to them.

Marble's filter output system is designed for these types of purposes. Below we show you how the system works and how to filter and capture output.

Filtering Output

<marble>

filter
{
  print("Hello world thats cool!");
  </marble>
  HTML OUTPUT CAN BE FILTERED TOO!
  <marble>
}
output(string s)
{
   # Anything outputted between the filter brackets {} regardless if the data outputted is in a file you included
   # the output will not be outputted but sent here for processing
   # The data is stored in variable "s" so we can do anything with that data now such as remove rude words from it or captialize it anything we like
   # But for now we will just print out what they outputted along with a message of our own
   
   # Without printing the data back out it will be as if they never printed anything
   print(s + "FILTERING IS COOL!");
}
</marble>

So you see filtering output is a powerful feature it can be used to ignore all output of a given scope or file and can even be used to filter out rude words. Filtering is great for when you need to inspect, use, or modify the data outputted in a marble scope.

What Now?

Congratulations you have finished the Marble's starter guide there is still however a lot to learn such as how to use Marble's powerful permission system allowing you to limit what plugins in your system can do as well as learning how to create your own system permissions!

You can also learn about how to use Marble properly with apache and receive "POST" and "GET" from the web client as well as process uploaded files.

Are you the type of person who would rather run Marble directly from the terminal? Well our standalone applications guide is just for you!

So if you choose to keep reading this guide you will first learn about Marble's powerful permission system we will then teach you all things web when it comes to marble and finally we will teach you all things for applications designed to run in the terminal.

What is the Permission System?

Marble has what's known as the permission system it allows you to restrict what any scope in marble can do. You can prevent a scope from printing, reading files in a certain location, writing files in a certain location and anything around security really. You can also create your own permissions so if you are a big system such as "Wordpress" you can restrict what plugins in your system can do allowing for a much more secure environment if those plugins are malicious or have vulnerabilities.

Every scope in marble is binded to a Permissions object this permissions object states what this scope is allowed to do. When a new scope is created in a scope; such as defining a "if" statement your current scopes permissions are passed to this new scope they inherit them. This means your child scopes can never do more than you can do.

You can not escalate your own permissions higher than your own permissions you can however limit the permissions of child scopes all of their children will then also inherit the limited permissions you provided.

Let's take a look at an example of us limiting a scope.

Limiting a scopes permissions

<marble>
print("I can print here as I have an IOPermission!");

# Create a new permissions object with no permissions in it
Permissions perms = new Permissions();
permission perms
{
    # Anything in here cannot print or do anything that requires permissions
    # such as writing, reading files and more
    # as we have binded this scope to a blank permissions object that has no permissions
    print("This will fail");
}
</marble>

You can see above that we can set a scopes permissions using the "permission" keyword this then binds the permissions to a Permissions object. In the above example we have binded the scope to an empty permissions object meaning that scope has absolutely no permissions to do anything. All scopes nested in the limited scope will also be limited this includes including or requiring files within the scope. If you run the above example you will see a PermissionException is thrown as you have no permission to print.

Let's now give our limited scope the ability to print

Giving our scope an IOPermission

<marble>
print("I can print here as I have an IOPermission!");

# Create a new permissions object
Permissions perms = new Permissions();
# Let's give this permissions object an IOPermission allowing it to print
perms.add(new IOPermission());
permission perms
{
    print("This will work!");
}
</marble>

If you look above we add a new IOPermission to the "perms" Permissions object and this allows printing in the scope we have limited access too. It will not be able to do anything else such as file operations or network operations as we have not given the scope the permission to do so.

If you try to add a permission to a Permissions object that you do not hold you yourself the system will throw a " PermissionException" as you cannot escalate your own permissions.

Limiting what variables scopes can see

Marble has functionality to allow you to limit what variables scopes can see. This plays an important part in the permission system to prevent plugins from accessing variables defined in the file thats loading the plugin that you do not what the plugin to know about. Such as database credentials!. Below is an example of how to limit a variables scope within Marble.

<marble>

number a = 30;
number b = 20;

limit
{
   number a = a;
}
scope
{
    # Prints 30
    print((string) a);
    # Fails as variable "b" is not declared
    print((string) b);
}

</marble>

So if you look at the above example we use a "limit" keyword and anything defined in that body is what we want the limited scope to be able to see. Where you see the "scope" keyword the body you see their is the scope we have limited and inside that scope we only have access to variable "a". Variable "b" we have no access too as far as Marble is concerned it does not exist.

Creating your own permissions

Marble allows you to create your own permissions a great example of when you would create your own permissions is in the case of a blog. If you created your own content management system blog that allowed people to create and use plugins you could limit what those plugins could do by creating your own permissions.

For example you might end up creating a PostPermission that must be held by the plugins in order for them to create posts in your content management system. If they do not hold the permission you would throw a " PermissionException". Let's take a look at an example of creating your own permissions.

Before we begin create a directory named "mycoolplugin" and create the following files in the correct destinations as described by relative paths below:
./mycoolplugin/coolplugin.marble
./index.marble

coolplugin.marble File

<marble>
class MyCoolPlugin extends Plugin
{
public:
    App app;
    function __construct(App app) : void
    {
      this.app = app;
    }
    
    function Init() : void
    {
       # Uncomment below to watch our plugin be denied access to printing
       #print("abcd");
    }
    
    function doAction(string s) : void
    {
       # Printing is still denied as we don't hold an IOPermission. The permissions are locked onto this object as we created
       # this object with limited permissions
       #print("abcd");
       
       # Let's call the function in App to allow us to print as we hold a MyPrintPermission
       this.app.do_print("abcdef");
    }
}

# Let's tell the App about our plugin by setting its value its expecting
return_value.set((Object)(new MyCoolPlugin(app)));
</marble>

The coolplugin.marble file is our imaginary plugin in our own imaginary content management system. You can see it extends classes we have not yet declared? Well we have declared them inside " index.marble" the file that loads our plugin. So let's explain whats happening here in " coolplugin.marble". We first extend the " Plugin" class which we defined in the " index.marble" file we then implement the " Init()" and " doAction(string)" methods from our super class. These are methods that are called by " index.marble" when loading and preforming actions on our plugin. We have limited the permissions of our cool plugin which means we can't do anything but write and read to our plugins directory and call the " do_print" method in the App class. All "do_print" does is print to the terminal it is the same as "print". You will notice the function call to "print" is actually commented out this is because if we did try to use that we would get a PermissionException thrown at us as our file "index.marble" has limited the permissions of our plugin "coolplugin.marble" it has no access to print.

You will notice that on the final line of the source file you see " return_value" and we set it to a new instance of our plugin. The " return_value" variable is declared in " index.marble" just before it loads our plugin its purpose is so we can pass an instance of ourself back to our " index.marble" file. The return_value variable is of type Value which is a class built into marble that can be set to any type.

index.marble File

<marble>
# This is our PrintPermission if plugins hold this they will be allowed to print using our special print routine we will make
class MyPrintPermission extends Permission
{
public:
     function __construct() : void 
     { 

     } 
     
     function __permission_check(PermissionProperty one, PermissionProperty two) : void
     {
       
     }
}

# As we have now created the MyPrintPermission our current scope has inherited the MyPrintPermission permission we created
# Our current scope right now is the global scope
# therefore MyPrintPermission is now a part of the global scopes permissions
# any objects we create will inherit the MyPrintPermission unless we tell it otherwise

# This is our base plugin class all plugins should extend this
pure class Plugin
{
public:
    function __construct() : void
    {
        
    }
    
    # This is our Init method and it should be overrided by all plugins
    pure function Init() : void;
    
    # This is our doAction method it is called on all Plugins whenever the App has to do an action
    # This is a pure method and should be implemented by plugins
    pure function doAction(string s) : void;
}

class App
{
public:
    # This is the plugin we will load. In a real life senario this could be a List or Vector and we would load our plugins and store them in this list
    # but for this example we will have only one plugin
    @Plugin plugin;
    function __construct() : void
    {
    
    }
    
    # The do_print function is a function that our plugins can call
    # to print to the screen
    function do_print(string s) : void
    {
        # Let's get the permissions of the scope thats calling us
        Permissions perms = getCallerPermissions();
        # Do they have a "MyPrintPermission"
        if (perms.get("MyPrintPermission") == null)
        {
           # They do not have a "MyPrintPermission" so they do not have permission to call this method let's throw an exception
           throw new PermissionException("You do not have the \"MyPrintPermission\" which is required for calling c_print");
        }
        print(s);
    }
    
    function Init() : void
    {
        # For this example we will only load one plugin that we know the path for before run time
        # In a real system you might loop through a database of plugins and load them one at a time with different permission scopes
        # Before we can load our plugin we must restrict its permissions let's do that now
        
        # Create a blank permissions object
        Permissions perms = new Permissions();
        # Add our MyPrintPermission to it
        perms.add(new MyPrintPermission());
        
        # We need to also add a FilePermission to our plugins directory
        # otherwise how are we meant to include a file if we have not given ourself the permission to do it?
        # Once we enter the "permission perms {}" our scope is entirely limited
        # So let's now give file access to the plugins directory
        
        # Create a file permission giving both read and write access to the cool plugin's directory
        FilePermission fp = new FilePermission();
        fp.setLocation("./mycoolplugin");
        fp.setCanWrite(true);
        fp.setCanRead(true);
        
        # Now add the FilePermission to the Permissions object
        perms.add(fp);
        
        # We are about to load the plugin. We expect our plugin to return an instance of Plugin to us
        # but how can it do that? Well this can work by creating a Value object before including the plugin
        # this value object can then be set by the plugin and we can later extract the Object value
            
        # Create a new Value
        Value return_value = new Value();
            
        # Now restrict the permissions of our file include to the permissions object we created
        permission perms
        {
            # We must now limit what variables can be seen in the scope for security reasons
            # to prevent this plugin accessing variables inside our object
            # we will limit the scope to have a reference to ourself and a reference to a return_value it can set to tell us
            # about its self
            limit
            {
                # Give the plugin we are including access to ourself and the return value we want it to set
                Value return_value = return_value;
                App app = this;
            }
            scope
            {
                # Finally include the plugin
                include "mycoolplugin/coolplugin.marble";
            }
            # Now extract the loaded plugin and store it
            this.plugin = (Plugin) return_value.getObject();
            # Initialise the plugin
            this.plugin.Init();
        }
        
        # We are now done here and the plugin we have loaded the plugin and now have a Plugin object thats bounded to only be able to access
        # its plugin's directory and print using our "do_print" method we have created
        # the standard "print" will fail for it.
        # These permissions are bounded to the plugin object for its entire life time
        # you can now safely call methods on the plugin and they will be binded to the permissions we created
        # The Plugin thats loaded will always be bound to those permissions they cannot be changed
        # for example if you were to limit permissions and call a function on this plugin the permissions will not be lowered
        # for the actual method call on the plugin because the permission system prioritises object permissions over ones you have set
        # therefore the system will choose the Plugin's permissions that it was created with.
    }
    
    # Simple fake dummy method that could be in a real life system
    function doAction(string s) : void
    {
        # We better tell our plugin about this action it may want to do something because of it
          this.plugin.doAction(s);
        
    }
    
}


App app = new App();
# Initialise the App which will load the plugins
app.Init();
# Now lets do an action for our system a fake action
app.doAction("/");

</marble>

The "index.marble" file is our main program here we create the "MyPrintPermission" permission which allows access for people to call our "do_print" method.  We also have a class of "App" which is our core of our application it is responsible for all things relating to this application and plugins can communicate with it. Most of what is going on is explained in the code as it is too complicated to explain while not referencing individual parts of the code however an important thing to note is that when you create a new instance of a class within marble the object instance will then hold the permissions of the scope you created the Object in. It will hold these permissions for its entire life time. This means that if you create a new instance of a class inside a scope that has limited permissions because you limited them any communication with that object even inside a scope with higher permissions will not grant that Object more access as it is bounded to the permissions that were available upon creating the object. This is why when we do "this.plugin.doAction(s)" we do not have to restrict the permissions to that method call as the permissions are already restricted for the plugin we have loaded. You also cannot override this behaviour once an Object is created it is stuck with those permissions.

Permission Properties

You may have noticed the "__permission_check" function in our "MyPrintPermission" permission class specified in the code in the last section. This function is called when ever you add a permission to a "Permissions" object and the variable values in the "MyPrintPermission" class your scope permissions holds are not equal to the "MyPrintPermission" variables you are trying to add to a new "Permissions" object.

So put simply the "__permission_check" function is called when your variable values differ from the variable values of the permission you are adding to your "Permissions" object you have created. Only the variables that are not equal are passed to the "__permission_check" function and you  are responsible for validating weather or not we should allow the creation of the "MyPrintPermission" even though the values differ from your own. If you do nothing then this will allow people to esculate their permissions for your "MyPrintPermission" permission class. You are responsible for validating that a given scope is allowed to create a permission object  with those changes. If you do not agree with this change you throw a "PermissionException" rejecting them from using this permission. Below is an example of how this works

<marble>
# This is our PrintPermission if plugins hold this they will be allowed to print using our special print routine we will make
class MyPrintPermission extends Permission
{
public:
     boolean can_print = true;
     function __construct() : void 
     { 

     } 
     
     # Property one is the permission property for the permissions
     # of the scope that is trying to add a new MyPrintPermission to a Permissions object
     # Property two is the permission property we are trying to set it to.
     # Both properties are related to the same property name
     # The __permission_check method is only called in the event that two properties from the different
     # MyPrintPermission objects differ. If they do then this method is called to resolve the problem and its up to thsi method to either accept the change or reject it
     function __permission_check(PermissionProperty one, PermissionProperty two) : void
     {
       # Whilst inside this object we have no access to "this" or variables within the MyPrintPermission class
       if (one.getName() == "can_print")
       {
           # getValue() returns a string so we need to convert it to an int as "true" == 1 and "false" == 0
           number oneV = (int) one.getValue();
           number twoV = (int) two.getValue();
           if (oneV <= 0 && twoV >= 1)
           {
              throw new PermissionException("You cannot esculate your permissions. You do not have a true value for can_print");  
           }
       }
       
     }
}

# As we have now created the MyPrintPermission our current scope has inherited the MyPrintPermission permission we created
# Our current scope right now is the global scope
# therefore MyPrintPermission is now a part of the global scopes permissions
# any objects we create will inherit the MyPrintPermission unless we tell it otherwise

# This is our base plugin class all plugins should extend this
pure class Plugin
{
public:
    function __construct() : void
    {
        
    }
    
    # This is our Init method and it should be overrided by all plugins
    pure function Init() : void;
    
    # This is our doAction method it is called on all Plugins whenever the App has to do an action
    # This is a pure method and should be implemented by plugins
    pure function doAction(string s) : void;
}

class App
{
public:
    # This is the plugin we will load. In a real life senario this could be a List or Vector and we would load our plugins and store them in this list
    # but for this example we will have only one plugin
    @Plugin plugin;
    function __construct() : void
    {
    
    }
    
    # The do_print function is a function that our plugins can call
    # to print to the screen
    function do_print(string s) : void
    {
        # Let's get the permissions of the scope thats calling us
        Permissions perms = getCallerPermissions();
        # Do they have a "MyPrintPermission"
        MyPrintPermission perm = (MyPrintPermission) perms.get("MyPrintPermission");
        if (perm == null || !perm.can_print)
        {
           # They do not have a "MyPrintPermission" so they do not have permission to call this method let's throw an exception
           throw new PermissionException("You do not have the \"MyPrintPermission\" which is required for calling c_print");
        }
        print(s);
    }
    
    function Init() : void
    {
        # For this example we will only load one plugin that we know the path for before run time
        # In a real system you might loop through a database of plugins and load them one at a time with different permission scopes
        # Before we can load our plugin we must restrict its permissions let's do that now
        
        # Create a blank permissions object
        Permissions perms = new Permissions();
        MyPrintPermission perm = new MyPrintPermission();
        # Here we set can_print to false disallowing our cool_plugin to print using our system
        perm.can_print = false;
        # Add our MyPrintPermission to it
        perms.add(perm);
        
        # We need to also add a FilePermission to our plugins directory
        # otherwise how are we meant to include a file if we have not given ourself the permission to do it?
        # Once we enter the "permission perms {}" our scope is entirely limited
        # So let's now give file access to the plugins directory
        
        # Create a file permission giving both read and write access to the cool plugin's directory
        FilePermission fp = new FilePermission();
        fp.setLocation("./mycoolplugin");
        fp.setCanWrite(true);
        fp.setCanRead(true);
        
        # Now add the FilePermission to the Permissions object
        perms.add(fp);
        
        # We are about to load the plugin. We expect our plugin to return an instance of Plugin to us
        # but how can it do that? Well this can work by creating a Value object before including the plugin
        # this value object can then be set by the plugin and we can later extract the Object value
            
        # Create a new Value
        Value return_value = new Value();
            
        # Now restrict the permissions of our file include to the permissions object we created
        permission perms
        {
            # We must now limit what variables can be seen in the scope for security reasons
            # to prevent this plugin accessing variables inside our object
            # we will limit the scope to have a reference to ourself and a reference to a return_value it can set to tell us
            # about its self
            limit
            {
                # Give the plugin we are including access to ourself and the return value we want it to set
                Value return_value = return_value;
                App app = this;
            }
            scope
            {
                # Finally include the plugin
                include "mycoolplugin/coolplugin.marble";
            }
            # Now extract the loaded plugin and store it
            this.plugin = (Plugin) return_value.getObject();
            # Initialise the plugin
            this.plugin.Init();
        }
        
        # We are now done here and the plugin we have loaded the plugin and now have a Plugin object thats bounded to only be able to access
        # its plugin's directory and print using our "do_print" method we have created
        # the standard "print" will fail for it.
        # These permissions are bounded to the plugin object for its entire life time
        # you can now safely call methods on the plugin and they will be binded to the permissions we created
        # The Plugin thats loaded will always be bound to those permissions they cannot be changed
        # for example if you were to limit permissions and call a function on this plugin the permissions will not be lowered
        # for the actual method call on the plugin because the permission system prioritises object permissions over ones you have set
        # therefore the system will choose the Plugin's permissions that it was created with.
    }
    
    # Simple fake dummy method that could be in a real life system
    function doAction(string s) : void
    {
        # We better tell our plugin about this action it may want to do something because of it
          this.plugin.doAction(s);
        
    }
    
}


App app = new App();
# Initialise the App which will load the plugins
app.Init();
# Now lets do an action for our system a fake action
app.doAction("/");

</marble>

If you want to try and test the "__permission_check" function and see it in action just simply try to add a "MyPrintPermission" permission object to a "Permissions" object from within "test.marble" you will see that your "__permission_check" function will throw a "PermissionException" denying the escalation of these permissions.

Processing GET

This is the first tutorial on the "Building Web Applications" guide for Marble. In this guide we will cover many topics on building web applications in Marble. We will start with the processing of "GET" parameters.

What is a HTTP GET?

A HTTP GET is information a web browser sends to a server that is present in a special format in the address bar. For example if you were to navigate to "http://127.0.0.1/test.marble?abc=true" then your web client would send a GET parameter named "abc" equal to the string "true".

Below is a simple application on processing "GET" within marble

<marble>
RequestArguments arguments = Request.getArguments();
if (arguments.has("name"))
{
    string name = arguments.get("name");
    # We should make the input safe against cross site scripting attacks
    # Almost like strip_tags in php but instead of removing tags it just makes them browser friendly
    # and not executable
    name = safe_tags(name);

</marble>
<i> Your name is: </i><b><marble>print(name);</marble></b>
<marble>
}
else
{
</marble>
Please provide your name e.g http://127.0.0.1/index.marble?name=Daniel
<marble>
}
</marble>

The RequestArguments class object holds all HTTP GET parameters that have been parsed by Marble and Apache.

Processing POST

You should all be aware of HTML forms and posting of these forms. In Marble you can capture the POST sent from the web client to your apache2 web server. This is very easy to do

Processing POST example is below

<marble>
    string fullname = "";
    
    # Get our POST content
    PostContent content = Request.getContent();
    if (content.has("submit"))
    {
        string firstname = content.get("firstname");
        string surname = content.get("surname");
        fullname = firstname + " " + surname;
    }
    
</marble>
<html>
<head>
<title>My post application example</title>
</head>
<body>
<marble>
if (content.has("submit"))
{
</marble>
<p>Thanks for telling us your name <marble>print(fullname);</marble></p>
<marble>
}
</marble>
<form action="test.marble" method="POST">
Firstname: <input type="text" name="firstname" />
<br />
Surname: <input type="text" name="surname" />
<br />
<input type="submit" name="submit" value="Show me" />
</form>
</body>
</html>

So above we have a file named " test.marble" when you submit the html form your full name is displayed

Handling File Uploads

In a lot of web applications you need the ability to upload and process files. Marble has full support for files uploaded with " multipart/file-data". We will now cover an example that allows you to upload a file and then redirects you to it.

Before we continue we will assume you are creating this file in your root web directory. If you choose to create it else where amend the source file below to suit your setup correctly.

Firstly create a new directory called uploads relative to the path where you will create your project.
Now your going to need to change the user group so that apache can write to this directory. You can do this using the command below

sudo chown myuserid:www-data ./uploads

Replace "myuserid" with your user id of your system you can find this by opening a terminal and you should see. userid@machinename the user id you see is the one to use. This just grants group ownership to apache allowing us to write to the uploads directory through our marble script.

Below is an the script you want to create for uploading files

<marble>
FileContent file_content = Request.getFileContent();
if (file_content.has("file"))
{
    # We can get the uploaded message here.
    # We won't do anything with it this is just a demonstration on how to get POST data
    # along with file data
    string message = Request.getContent().get("message");
    
    # Now lets get our file
    MultipartFile file = file_content.get("file");
    
    # BELOW ARE WAYS TO USE THE FILE BUT THEY ARE COMMENTED OUT
    # print(file.getName()); # Prints file name
    # print(file.getType()); # Prints the file type e.g video/mp4
    # print(file.getExtension()); # Prints the file extension e.g .mp4
    
    # Let's move the file into our uploads directory
    string path = file.getPath();
    File.move(path, "./uploads/" + file.getName());
    
    # Let's now redirect the user to the file
    Response.setHeader("Location", "http://127.0.0.1/uploads/" + file.getName());
}
</marble>
<form action="index.marble" method="POST" enctype="multipart/form-data">
<input type="text" name="message">
<input type="file" name="file">
<input type="submit" value="Upload!">
</form>

You will notice we redirect to the file after uploading it. We do this by setting  a HTTP header for the response back to the web client. Http headers are very powerful at controlling the web browser. You require a HeaderPermission to set HTTP headers and if you try to set cookies using Response.setHeader you also require a CookiePermission.

Cookies

Cookies allow you to store temporary data on the web client. Marble provides a very simple mechnism for using cookies we will now cover how to set and read cookies within Marble. Firstly to manipulate cookies you require a CookiePermission something that is enabled by default for any fresh install of Marble.

Cookie set and read example

<marble>
# Sets the cookie "abc"
Response.setCookie("abc", "hello world");
# Ge the abc_cookie and print it out
string abc_cookie = Request.getCookie("abc");
print(abc_cookie);

# the cookie will not be seen on the first run as we set the cookie but we have
# already received the clients cookies so setting it for this session
# does not make it available until the client has received the cookie
# and has requested from us again
# Refresh the page once again and you will see the cookie outputted
</marble>

Setting and reading cookies is easy in Marble but it is important to know that when you set a cookie for the first time it will not be available for the rest of this instance. A refresh will be required this is because the web client never sent you that cookie. You only just told it about it. This is why when setting cookies you will not be able to get them until the client has reloaded your web page.

Sessions

Sessions in Marble allow you to store information about a user but on the server side. The client will maintain a session key that they will send to you as a cookie this will then be used to select the correct session on your web server. Sessions are great and powerful as they allow you to securely store information temporarily about a user on your server. Sessions should be used for storing data that you are willing to lose and that you only plan to use for a short time. This can be things such as whether a user is logged in or not or the users language preferences.

Sessions in Marble work a little different than they do in other programming languages. Since Marble is based entirely on security you are required to provide a session password when creating or opening sessions. A Marble session is split into session banks and each session bank has a password. The user provides the session key which gives you the session. You provide the session password which unlocks you a session bank in that users session. This allows different parts of this system to access the user session but never see or manipulate session data that was created in another part of the system. This prevents plugins from manipulating your sessions and doing dangerous things with them. If you did want a plugin to modify your session data it would need your session password which you could provide if you wanted it to have access to your session bank.

So let's demonstrate on how to create sessions in Marble

Session Marble Example

<marble>
FileSession session = new FileSession();

# Create a new session or load an existing one and access the Session bank with the password "mysessionpasswordkeepthisrandomandunique"
session.create("mysessionpasswordkeepthisrandomandunique");

# Lets set a session string
session.setString("name", "Daniel");

# Many other methods exist BELOW COMMENTED
# session.setNumber("abc", 30);
# session.setObject("abc", new Object());
# session.getNumber("abc");
# session.getObject("abc");
# session.has("abc")

# Once you have loaded this script once. Comment the line where we set the session string called "name"
# and then rerun the script you will still see "Daniel" printed
# as you have it still stored in the session so we 
# do not need to set it again

print(session.getString("name"));

# Sessions must be saved or your changes will be ignored
session.save();


</marble>

So you can clearly see when we do "session.create" we are passing our bank password to unlock the session bank of the session for the user. All sessions have to be saved or your changes will be ignored. Once you have your session string set and can still see it printed when refreshing the page even though you have commented out where you set the session string "name" you are then ready to test changing your session password. Change your session password and you will see that it can no longer find your session string by the name of "name" this is because you are no longer in that session bank. Change the password back and refresh the page and you will see it outputted again. Hopefully that explains how the session passwords work.

Simply put when a user visits your Marble script a session is created for them. When you do "session.create" you are creating or loading a session bank for the given user that requires your session bank password to unlock it. It should also be noted Sessions can also work outside of apache and are available for standalone Marble applications that run in the terminal as well

Using Marble

In this short guide we will teach you how to use marble for terminal based applications. Firstly open up your Linux terminal and execute the command " marble". By typing " marble" and pressing enter. This will show you instructions on how to use the marble application in the terminal and will show you how to do things such as change the configuration.

Processing Argv

If you have programmed before you will know about processing arguments passed to your application when its first started. Weather you have experience with Java or experience in C or C++ many languages have the ability to do this. Marble has the ability as well. We will demonstrate how you can process arguments in Marble.

Let's first create a simple Marble application below and save it as "file.marble"

Processing Argv example

<marble>
string[] arguments = System.getArguments();

# Prints the filename of your script
print(arguments[0] + "\n");

# Additional passed arguments
for (number i = 1; i < arguments.size(); i+=1)
{
    print(arguments[i] + "\n");
}
</marble>

Now let's run our application and pass some arguments to it

marble file.marble "This is my second argument" "This is my third"

So you can see how easy it is to take in arguments from your Marble application.
The first argument which is index zero is the filename of your script. Additional arguments are arguments passed to your application and start at index one onwards.

Web applications also have arguments but only one argument and that is equal to the filename of the script you are running

Extra Material

You have finally read all of the beginners guide material. All we can do now is point you in the direction of library usage examples where you can view Marble examples of using Marble libraries such as libraries that allow you to communicate with Mysql databases or handle Dates and much more.

Click here to download Library materials and click here for an API reference for Marble standard libraries.

The Marble project solely relies on one person so donations would be greatly appreciated to help keep Marble strong

Donate today and help Marble grow

Having the support of Marble enthusiasts helps us grow. We will use your donations to dedicate more time to the Marble project and purchase paid advertising to help get Marble more known.

[Don't want to donate?]: If  you don't want to donate that is fine we will never give up on Marble and keep working on it. If however you do want to donate please click the button below. Thank you.

Donate