ionCube Logo
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


 
Post new topic   Reply to topic    ionCube Forum Index -> ionCube PHP Encoder

encoding files and license

Author Message
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Fri Oct 07, 2005 9:16 pm    Post subject: encoding files and license Reply with quote

Hello,
I read the manual and also did some tests, but now I'm a little confused. I also have some questions.
starting point:
My application is delivered in modules, I have a root folder containing an index-file with a frameset that loads the rest. Besides others I have a folder that contains module folders with scripts. I also have conf folder in root that contains some encoded and unencoded configuration files + the license file.
-root
-index.php
-+conf
-+modules
---+mod1
---+mod2

I'm also using non-standard file extensions for included module files.


Please correct the following if I'm wrong
Now, to encode the files with include-protection I do it like already posted here,
First step:
I first encode everything in the modules-folder and the files that are to be encoded in the conf-folder. To do this I set a property eg.
--property "my_property=thisismyfile"
with the ioncube_encoder.
This property is no variable that I have to code into the php-scripts.
To restrict the inclusion, now I add the option
--include-if-property "my_property=thisismyfile"
and finally encode the files.

Second step:
I encode the index.php with all options I used to encode the first-step-files but
--include-if-property "my_property=thisismyfile"

Third step:
I create the license file with the option --enforce-property my_property

Is this procedure correct?

Now to some small questions:
--disallow-untrusted-extensions
Since I use some custom extensions, normally I would need to specify somehow that this file extension is a trusted one.
How do I do this, or does the encoder recognize these as trusted because I told it to encode them?

--select-server-adapter, --select-adapters
This is only used with server data files to generate the license file directly using the data from that file?

7.3 License Validation
Is this a set of functions that can be used to redirect the a php script to a custom action? If so, could somebody post a small example?

Many thanks in advance

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Fri Oct 07, 2005 11:55 pm    Post subject: Reply with quote

Well,
I've been testing around with the include-file-protection a little bit.
The encoder/loader behaves as expected, I assume.
But this runs me into a little problem with the configuration files. These are PHP-files that are included as needed by include or include_once.
They contain parameters that the customer changes when configuring the application.
As soon as the user changes a param the file is being rewritten to disk, this means no encoding.
If now an encoded module file includes one of the plain (php)config files the loader throws an error saying that file X is trying to load is an unencoded or invalid file.
The behaviour is correct, the effect means trouble.

Is there a way or workaround to make it work the way I need it and keep the protection. (Many of my Scripts include the config files)

Thanks in advance & best regards

Ralf

PS: seems the only solution I found is file operations to read configs, I already found some read_ini_file() which has nothing to do with the php.ini but the structure. Defined conf-options are passed to an array.
This throws me back e few days. The other possibilityis to store config in a database, but to tellyou the truth, I don't know if this would be a better solution.
Back to top
View user's profile Send private message Send e-mail
liaison
ionCube Support


Joined: 16 Dec 2004
Posts: 2788

PostPosted: Sat Oct 08, 2005 11:11 am    Post subject: Reply with quote

Reading and processing config files in your program is a much better way in some respects than reading a PHP file. Security can rarely just be bolted on, and has to be considered at the design stage and not just as an afterthought. Sadly, for many an afterthought is exactly what it is, but you should consider whether your application is fundamentally insecure.

The include attack protection offered by the Encoder is a very complete and strong solution, as you have discovered yourself, but if your application design needs to include a plain text PHP file, which could execute arbitrary code, then you're not getting the maximum benefit. However, it can be done, and you need just to encode the file that directly includes the plain text file so that it doesn't require the included file to be encoded. With many files including the config file, what may help is to have an encoded wrapper around the config file, and for you to include the encoded wrapper rather than the config file directly. In this way, all the files that include the config wrapper can still require the wrapper to be encoded, just as with all the other files and so everything remains consistent, and you just encode the wrapper so as to be able to include the config file as unencoded.

I would consider parsing a text file though. If all you have is key value pairs, then it's pretty trivial. Read a line at a time, trim both ends, reject empty lines, and use the regexp functions or even just substr to reject comment lines. For each interesting line, find the first space and split the line in two. The first string is your key, the second the value. Run a trim on the second to take off leading spaces, and you have your key and value. Put into an associative array and you're done. You might make a sanity check on the file size first in case a moron is trying to use a 10M binary or 700M movie as the config file just to see what happens. You can get quite creative in how you choose to handle those situations if you so wish.

For more sophistication you could allow a dot in the key to support sub keys. e.g.

server1.mango.ip : 1.2.3.4

would be equivalent to

$config['server1']['mango']['ip'] = '1.2.3.4'

This is also pretty trivial, but powerful as you can now represent arbitrary hierarchies. To do this, with the key that you obtained during the first set of processing, now split the key around dot ('.'). The PHP function to do this will give you an array of the individidual strings. Now you need just to walk the array, at each stage putting a reference (using &) to the config array sub-element into a variable, and once done, you'll have the reference to the final element to which you assign the value. This is a general solution that would also work if the key had no dots in it, so there's no special case there.

Half a days work in the coding and testing, (really half a morning but allowing for interruptions), and then the rest of the day to rejig your sample config files if they are quite complex. To avoid having to change how your application gets the variables, and given that you have a wrapper that reads the config file, the wrapper can put the config data into the relevant variables so that the code including the wrapper behaves just as before.

If your config files set individual variables as opposed to an array, this technique also ensures that only the variables that are expected to be set will be. A well written program wouldn't be compromised in any way by a hacker setting arbitrary variables, but many programs are poorly written to assume that variables start off empty, behaving differently and possibly badly if they're not. For that reason it's best not to allow config files to set arbitrary variables. This, incidentally, is why the feature in PHP that sets variables directly based on GET or POST parameters should be turned off.
_________________
Community Admin
Back to top
View user's profile Send private message
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Sat Oct 08, 2005 12:45 pm    Post subject: Reply with quote

Hello nick,
many thanks again.
After I found out yesterday, last night that protection wouldn't work as expected the way I use config files, I started analyzing the situation and the alternatives. I have 6 modules involved in that problem.
I googled, yahooed around for possible alternatives and found a solution that I might be able to impement pretty quick, in max a day.
Starting point was the PHP function parse_ini_filehttp://php.speedbone.de/manual/en/function.parse-ini-file.php which allows to read ini-like (php.ini) flat files, with sections, into an array.
After some reading, I found out that this functions wouldn't suite my needs exactly since there are some caveats like restrictions on values and keys that are allowed to use.
But this pointed me into the right direction.
What I'm going to do ist to write a small class to read and write such a config file. The config files are written just in one module, to change the part that writes the file is easy. I keep the cration of the configuration array like it is, but instead of formatting the string to be saved into the actual php file, I pass it to the class-function I'll create today.
In the modules using the config I just have to change include/include_once to the function that reads the config file making sure the result is the array I used before.
I'll tell you tomorrow about the results on this.
The point with the variable writing you mentioned is pretty interesting, I've seen that in Typo3 (CMS), the also use flat text files with configuration /setup settings the way you described.
Eg:
plugin.my_plugin.setting1 = whatever
it is then converted to something like
$globalconf["plugin."]["my_plugin."]["setting1."] = "whatever";
The dot tells the code that it is a key and not a value.
They even use "{}" to encapsulate key/value pairs like

plugin.my_plugin{
setting1 = whatever
setting2 = this
}
which is equivalent to
$globalconf["plugin."]["my_plugin."]["setting1."] = "whatever";
$globalconf["plugin."]["my_plugin."]["setting2."] = "this";
I don't know exactly why they keep the dot in keys after conversion, but I think this is to prevent a key from being accidentally interpreted as a value.

As I said, I'll tell you tomorrow how hard it was.
As soon as I'm finished I might write some documentation/tutorial on my experiences and post it here.
But one last question that is still moving around in my head.
The property that is set with the encoder has not to be coded into the php files manually, right? The are only an ioncube encoder issue.

Many thanks again,

Ralf
Back to top
View user's profile Send private message Send e-mail
liaison
ionCube Support


Joined: 16 Dec 2004
Posts: 2788

PostPosted: Sat Oct 08, 2005 1:57 pm    Post subject: Reply with quote

Quote:
The property that is set with the encoder has not to be coded into the php files manually, right? The are only an ioncube encoder issue.


Right. Properties are a concept that is separate to PHP, and implemented as part of the metadata in the files. There is an API function to return the properties associated with the file that is calling the function (by design and for security, you cannot read properties for arbitrary files), but all operations that test properties are performed by the Loader on the metadata that the Encoder put in the files. The PHP code isn't changed, and you don't need to change the PHP code itself to define properties.
_________________
Community Admin
Back to top
View user's profile Send private message
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Sat Oct 08, 2005 2:27 pm    Post subject: Reply with quote

Many THANKS Nick,
I'll report my results here as soon as I'm finished.
Have a nice weekend

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Mon Oct 10, 2005 2:55 am    Post subject: Hello nick Reply with quote

Hello nick,
as I said in my last post, here is a little what happened w lots of banging my head against the wall and a class I've written to read/write configuration files.
Since I wanted to profit from the include-protection of the encoder, I had to sit down and think about how to make the best out of my situation.
The main problem is that my configuration is stored in a multi-dimensional array, standard read/write functions or classes, at least the ones I found, don't work. Convert everything to flat one-dimensional would take me days or maybe weeks to change and test.
Why easy if complicated does the job?
So I went the harder way and wrote a class that I would like to share with other people here that might have or might run into the same trouble.
A configuration array like the following

Code:
$config["var1"] = 12345;
$config["var2"]["svar1"] = "varsvar1";
$config["var3"]["svar1"] = 5243;
$config["var3"]["svar2"] = "this
  var is
 
  far
  too long for one line";
$config["var4"] = "end of config";


is stored to the configuration file like this:

Code:
var1 = 12345;
var2.svar1 = "varsvar1";
var3{
      svar1 = 5243;
      svar2 = "this
  var is
 
  far
  too long for one line";
  }
var4 = "end of config";


Notice the multidimensional storage and svar2 which has a multi-line value.
Reading as well as writing is done with just one call:

Code:
<?php
//Reading
$res = new RWClass("myconf.conf");
//$res->fileconf returns the configuration file as an array
//$res->return_code returns error code, if any

//Writing
$res = new RWClass("myconf.conf", $input_config_arr, "w");

//$input_config_arr is the configuration array consisting of
//$config["params"] = the configuration array itself
//$config["comment"] = comment or header that will be set before the configuration itself (Preamble, usage instructions, warnings, etc)
?>


I tested the class standalone because I didn't have the time to test it with my application yet, and worked OK.

Interested people can download the class here Download PHP RWConfig Class

I wrote this class in a little of a rush and I'm pretty sure some things can be done better, but this is an emergency birth.
Comments, bugs and improvement suggestions are always welcome.
Tomorrow I'll build it into my application, this will be the easier part,
now I just have to change
include("configuration.file");
with
include("rw_class.php");
and write two aditional lines to get it to work instead of rewriting tons of code or going for an unsecure solution.

Well, that's it for right now.

Nick, thanks again

As soon as I'm finished with implementation and encoding I'll try to write a little tut on encoding. So stay tuned.

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
gator



Joined: 05 Oct 2005
Posts: 8

PostPosted: Tue Oct 11, 2005 9:50 pm    Post subject: Reply with quote

Hi Ralf, this may be obvious but just in case some one else reading this tries this....

If you use a text config file you don't want to use it for your database login and password info. If this file sits along side your application then the whole world can read it if the file extension is not .php.

Enjoy.
Back to top
View user's profile Send private message
liaison
ionCube Support


Joined: 16 Dec 2004
Posts: 2788

PostPosted: Wed Oct 12, 2005 12:52 am    Post subject: Reply with quote

This is a good point. We would recommend using one of the crypto functions built into PHP to lock down the text file, and of course having the encode/decode routines encoded by the Encoder!
_________________
Community Admin
Back to top
View user's profile Send private message
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Wed Oct 12, 2005 9:31 pm    Post subject: Reply with quote

Hello nick, hello gator,
if I would use it to store logins, etc, this would be really a good point, but I don't.
I wrote this to store some configuration data like layout defaults, etc.
But you're absolutely right, I would never suggest using the class to store classified information, unless the file is stored outside the webservers document path or encoding the information.

But nevertheless, this is really an argument to consider, even for use to store to store non-crucial data.
I'll give it a go with rijndael encryption just before storing the whole string, with key and vector. Rjindel passed all relevant tests, as far as I know it will be implemented with AES in the future.

BTW, I just went back to encoding my program with include-protection using plain config-files. The encoder really works like a charme.

I've already run some tests, and encoder/loader works perfect.

Nick, one question,
I'm releasing my application with MAC-Restriction, I read in a different post in your forum that MAC-checking is going beyond OS-level, which would mean that such programs that can imitate MACs would be useless. I've heard of programs doing that especially on Windows systems.

Is this right?

OK, I'll keep you informed

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Mon Oct 31, 2005 11:54 pm    Post subject: Reply with quote

Hello all,
it took a little longer than expected, but I was pretty busy.
But now, as promised the little tut on encoding.
First of all this is the way I do it at the moment, and it works for me, so please don't expect an "this is all what is to say about encoding and there is no better way" tutorial.
Any comments or hints on how to improve this are welcome.
Before I forget, I did some little rework on that RWConfig class.
As posted in this thread before, unencoded configuration files are always a risk, they could be read by unauthorized persons, manipulated, etc.
I said that I would give mcrypt with rijndael encryption a try, after lots of reading and thinking things over I rejected that thought. The problem is not rijndael, the problem is mcrypt itself, to be more precise, I found too many ifs & buts related to that module ( eg. encoding might fail depending on OS and/or PHP version, etc.).
Since I just need to prevent manual editing of the file, I chose a pretty simple way to encode them.

Code:
function encode($str=""){
  return chunk_split(base64_encode($str));

function decode($str=""){
 return str_replace( "\r\n", "",base64_decode($str));
}


It might not be really safe, but it is clean enough to tell the user/customer: "Sorry, you can't edit this file manually!!".
I already uploaded a new version of the class, so if somebody is interested:

Download PHP RWConfig Class

OK, now to the encoding matter.
My application is structured as follows:

+root
--opensourceclass
--configuration folder
--module folder with sub-directories
--document folder
index.php

Encoding specs:
+property
+MAC-binding
+include-file protection
+use of project file
+use of license file

The following method works with and without the use of a license file, you just need to delete the license related directives if you are not using a license file.
One little comment on project files. After a while of banging my head against the wall trying to find out why the project file wasn't read correctly by the encoder, I found out that if you use line breaks or put more than one white space between each directive, the project file seems to be ignored, I don't even got no error message returned by the encoder.

Properties/Include file protection:
Properties are a nice feature to give your encoded files some extra protection by specifying key-value-pairs that are checked by the loader at run time.
These properties do not have to be specified within the php-files, you only need to specify them at encoding time:

--property "myownproperty='any property parameter or comment'" (don't forget the single quotes)

You can add more than one property.

The protection works when setting the directive
--include-if-property "myownproperty='any property parameter or comment'"

Say you have a file called file1.php that with the function
include("file2.php"); //also valifd for include_once(), require(), require_once()
and, of course the file file2.php with some other code.

The protection works in both directions, first it prevents file1.php from including a wrong file2.php, either unencoded or with the wrong property, second it prevents file2.php from being included by a wrong or unencoded file.
Example:
My file1.php is encoded but I replace my file2.php with a different unencoded or encoded file but with no or wrong property named file2.php.
The loader will return an error right away and will stop loading the scripts. Nice.

The only thing you have to pay attention to is that any script that includes other files that are not encoded must be encoded only with the directive --property "myownproperty='any property parameter or comment'". If they are encoded with both --property and --include-if-property the loader will return an error. The loader will also return an error if the top most file, normally some index.php in the document root is encoded with both directives.

If you have the encoder with the license generator, you can even use another directive to even enforce the protection when generating the license file:
--enforce-property "myownproperty"

Just a little remark that confused me a minute. The directive --only-include-encoded-files has nothing to do with the include file protection.

MAC-Binding:
Personally I love this feature, it makes sure that I will not find any copies of my application on other places than the one it was encoded for.
Theis only one thing to mention, if you don't have the encoder version with the license file generator, all scripts have to be re-encoded each time you want to install the files on a machine with a different MAC-address, but this is just a very small price you have to pay for this security plus.
Having the license file generator, you encode the PHP-files once and pass the MAC-Address-Protection to the license file.
The directive looks like this:
--allowed-server {00:11:22:33:44:55}

License-file generation, if available is a really nice feature because makes life a little easier, you just have to encode the php files once, the customers could then download the php files from a central place, and you just have to create a license files with custom restrictions that you then eg. send to the customer attached to an email. First I was worried that the license file feuture wouldn't work with my application because of my application structure (folders with sub-folders and so on). But it works, I put the license file into the configuration folder and added the following directive to the project file:
--with-license conf/altbus_license
where conf = configuration folder. I just see one problem that I didn't test yet. I don't know if this also works if the application is installed in a sub-directory of the document root. Does the loader look for the license file in a sub-directory relative to index.php or relative to the document root?
OK, maybe Nick could answer this without having to test it myself.
One last thing, any restriction you use to encode the files will be overridden by the same setting in the license file.
Example:
If you used --allowed-server {00:11:22:33:44:55} to encode the files, and used --allowed-server {FF:22:AA:33:BA:55} to create the license file, the setting that you used to encode the files will be ignored by the loader.

Basically I give my application a three-pass encoding run.
1. The first pass encodes all the files but index.php and a wrapper file that is used to include the open source classes (ADODB & ezPDF). This uses --property and --include-if-property
2. The second pass encodes the index.php and the wrapper file. Only --property is used
3. The third pass is used to create the license file (make_license) to set the restrictions

One word to restrictions. I also use restrictions like --allowed-server on pass 1 & 2. I set the MAC address to an address I own. I personally think this improves security and does not harm because that setting is overridden by the --allowed-server directive in the license file.

1st Pass
My first project file prwincl.txt contains something similar to this:

****prwincl.txt content begin****

--merge-target --include "*.dmb" --copy "*.css" --ignore "*.enc" --ignore "Docs/" --ignore "*.ori" --ignore "*.*~" --ignore "*.*~~" --ignore "*.*.bak" --ignore "*.*.orig" --ignore "*.*bak" --ignore "*.*orig" --ignore "*.copy" --ignore "index.php" --ignore "wrapper.inc" --ignore "*.pdf" --ignore "*.sql" --add-comment "This application is property of MYCompany Inc C 2005 "--message-if-no-loader "'ionCube loader modules not found, please contact our support Tel: 555-5555'" --loader-event "corrupt-file=File %f is corrupt, please contact our support Tel: 555-5555" --allowed-server {00:11:22:33:44:55} --loader-event "no-permissions=The application runs on a non-authorized server, please contact our support Tel: 555-5555." --property "mypropertykey='mypropertyvalue'" --include-if-property "mypropertykey='mypropertyvalue'" --loader-event "unauth-including-file=File %f was included by an unauthorized file" --loader-event "unauth-included-file=File %f tried to include an unauthorized file" --with-license conf/altbus_lizenz --passphrase "thisismypassphrase" --loader-event "license-not-found=Your license file could not be found. Make sure it is placed in the conf directory of the application." --loader-event "license-property-invalid=Error in file %f: a required dependency was not matched" --loader-event "license-corrupt=Your license file is corrupt, please contact our support Tel: 555-5555" --loader-event "license-header-invalid=Your license header is not valid, please contact our support Tel: 555-5555" --loader-event "license-server-invalid=The license file you are using is not valid for the actual server" --no-short-open-tags --strict-php --disallow-untrusted-extensions --verify --optimise max

****prwincl.txt content end****

I'm only going to explain the relevant parts, the rest is partially self explanatory or well explained in the manual. The relevant sections are highlighted.

RED: First section is used to restrict the server to the specific MAC address, which is my own and will be overridden by the same restriction in the license file. If you don't have the license generator, customer's MAC would have to be placed here. This is followed by the message that should be shown if the MAC address does not match.

GREEN: This section represents the include file protection followed by the messages that should be shown if a file tries to load another invalid file or a valid file is loaded by an invalid one. Note that both --property "mypropertykey='mypropertyvalue'" --include-if-property "mypropertykey='mypropertyvalue'" are used.
INDIGO: --ignore "index.php" --ignore "wrapper.inc" is used to neither encode or copy these files, because they will be encoded in the 2nd pass (see description on Properties/Include file protection above).

BLUE: Third section is used to activate the use of license files where
--with-license conf/altbus_lizenz specifies path and file name of the license file.
--passphrase "thisismypassphrase" is a feature used to make licensing more selective or individual. If you don't specify this, any license file you create will activate any application you have created.
If you don't own the license generator, then just ommit the section.
Example:
You have created two applications: Application A and Application B
Customer Doe buys Application A but not Application B
No matter how, but Doe gets Application B from an illegal source, or if you make the application centrally downloadable from your server even legally.
He copies his license file to the configuration folder of Application B, et voila, he will have a useable and free copy of Application B.
Specify a pass, --passphrase "thisismypassphraseforapplicationA", and another one, --passphrase "thisismyotherpassphraseforapplicationB". This way he will not be able to activate Application B with Application A's license file.

This is followed by the messages that should be shown if no license file was found or in case of a corrupt license file, etc.
If you don't own the license generator, then just ommit the section.

Now we encode:
./ioncube_encoder --project-file prwincl.txt /path/to/application --into /target/path --verbose

2nd Pass:
Now we need to encode the index.php and wrapper.inc.
As already said, this time we need a different encoding because loader would stop loading else (see description on Properties/Include file protection above).
My second project file prwoincl.txt contains everything in prwincl.txt but
INDIGO: --ignore "index.php" --ignore "wrapper.inc" (these are the two files that we want to encode in this pass)
GREEN: --include-if-property "mypropertykey='mypropertyvalue'" (to make index.php loadable and enable wrapper.inc to load/include unencoded files)

Now we encode:
./ioncube_encoder --project-file prwoincl.txt /path/to/application/index.php --into /target/path --verbose
./ioncube_encoder --project-file prwoincl.txt /path/to/application/modules/wrapper.inc --into /target/path/modules --verbose

OK, now you could zip the target directory and upload it to your server to let your customers download the application.

If somebody now buys your application, he sends you the MAC-Address the application is going to be attached to. Now you need to create a license file:
./make_license --passphrase "thisismypassphrase" --allowed-server {CU:ST:SM:AC:AD:DR} --enforce-property "mypropertykey" --header-line "This license is only valid for Mr Smith, license authority MyCompany" -o /output/path/altbus_lizenz

The license will only work with the application that was encoded with the passphrase --passphrase "thisismypassphrase", and only on the machine with the network adapter that has this address --allowed-server {CU:ST:SM:AC:AD:DR}, and only with files that were encoded with the property mypropertykey, --enforce-property "mypropertykey". The header line is optional, but has a warning character. Everybody can see that the license owner is Mr Smith and the license Authority is MyCompany.

If you don't have the encoder with the license generator or don't want to use it, simply ommit the parts related to license files.

OK, this is it.
If I'm wrong on something, please correct me within this thread. Like always in life I tried to write this little guide based on my experiences with the encoder and loader. There might even be a more powerfull protection. If so, everybody is invited to post improvements.

Well, last words ENJOY and happy encoding.

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
liaison
ionCube Support


Joined: 16 Dec 2004
Posts: 2788

PostPosted: Tue Nov 01, 2005 12:10 am    Post subject: Reply with quote

Excellent post Ralf, many thanks for contributing this!
_________________
Community Admin
Back to top
View user's profile Send private message
ralfk



Joined: 28 Sep 2005
Posts: 27

PostPosted: Tue Nov 01, 2005 12:14 am    Post subject: Reply with quote

Thank you Nick & you're welcome.

Best regards

Ralf
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    ionCube Forum Index -> ionCube PHP Encoder All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum