LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices


Reply
  Search this Thread
Old 01-07-2019, 02:43 AM   #16
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761

Quote:
Originally Posted by playker View Post
Yes, it is another method which could be used, I've seen something similar when looking at past threads about Adobe Air. I can understand why some people will prefer this method, but it's hard to tell if Air applications will always work correctly when started this way (using the SDK instead of the runtime and using "adl").
I would be very surprised if the SDK did not work equally well and this seems to be how others on other distros are handling the situation

https://wiki.archlinux.org/index.php/Adobe_AIR

P.S. This has come up on the Slackware forum before.

Last edited by ruario; 01-07-2019 at 03:04 AM.
 
Old 01-07-2019, 03:31 AM   #17
playker
LQ Newbie
 
Registered: Nov 2009
Location: Poland
Distribution: Slackware 14.2
Posts: 18

Original Poster
Rep: Reputation: 8
And I wouldn't be surprised if this method with the SDK didn't work equally well, but I don't know much about Adobe Air, so I may be wrong. That's why I use it as delivered by the upstream instead of relying on modded and untrustworthy software like what can be found in AUR (Arch users repository) with Adobe Air applications in that repo.

I had quickly read the thread you linked, before posting mine. Some people didn't get their Air apps working well.

Quote:
Twhirl

Twhirl works. But it doesn’t remember your login password. Retyping it is not a problem. But for FriendFeed, entering the remote key repeatedly is not fun . This means Twhirl will start anew unless your computer runs 24/7.

TweetDeck

The window shows up, but it’s useless, doesn’t run at all. The terminal shows a lot of errors. Quite disappointed
It's possible that not all Air applications will work on Linux, even with the official runtime and launcher, but at least people have the choice to try more than one method.

Last edited by playker; 01-07-2019 at 03:57 AM.
 
Old 01-07-2019, 05:23 AM   #18
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
I decided to download Adobe AIR 2.6 and e-Deklaracje in a clean Slackware 32 VM and see if I could get e-Deklaracje running without using rpm. In short it is not that hard.

You can manually install the AIR 2.6 runtime like this (assuming you agree to the AIR License):

Code:
# Fetch Adobe AIR 2.6
wget http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRInstaller.bin

# Extract Adobe AIR
mkdir air
tail -c+6705 AdobeAIRInstaller.bin | xz -qqd | tar Cx air

# Accept Adobe AIR EULA (as regular user)
mkdir -p ~/.appdata/Adobe/AIR
printf 2 > ~/.appdata/Adobe/AIR/eulaAccepted

# Install Adobe AIR (as root)
cd air/build
find etc opt \! -type d -print0 | cpio -R0:0 -p0d /
Once this is done, installing and launching e-Deklaracje is not a lot more work. Air apps are just .zip files with the contents of the app minus a small stub executable. It would appear that all the apps actually use the same stub executable, and it is included within the main runtime package (‘/opt/Adobe AIR/Versions/1.0/Resources/appentry’). To install, you just have to place all the files correctly (relative to each other) and then everything can be run, entirely bypassing the rpm/deb package creation steps.

For example, this is what I did to get e-Deklaracje to launch. I'll admit I could not test it a lot further because I am neither Polish, nor do I live there.

Code:
# Fetch e-Deklaracje
wget https://www.podatki.gov.pl/media/3103/e-deklaracjedesktop.air

# Extract e-Deklaracje
mkdir -p edeklaracje/share
unzip e-deklaracjedesktop.air -d edeklaracje/share

# Install e-Deklaracje (as root)
find edeklaracje -print0 | cpio -R0:0 -p0 /opt
install -Dm755 /opt/Adobe\ AIR/Versions/1.0/Resources/appentry /opt/edeklaracje/bin/edeklaracje

# Launch e-Deklaracje (as regular user)
/opt/edeklaracje/bin/edeklaracje&
Like the SDK trick, this is a truly cross distro method as no rpm is required, as you stated was your original goal.

Quote:
Originally Posted by playker View Post
The same method could also work on other distributions such as Arch with a little modification.
P.S. It wouldn't take much effort to configure desktop files and icons and wrap these two up in a couple of SlackBuilds, to get you native packages.

P.P.S. As a further test I also tried installing and running another AIR based app (Conqu) by adjusting the e-Deklaracje steps and it seems to work as expected.

Last edited by ruario; 01-08-2019 at 05:53 AM. Reason: undid earlier edit, simplified e-Deklaracje install command; added comment about Conqu
 
1 members found this post helpful.
Old 01-07-2019, 05:25 AM   #19
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
Quote:
Originally Posted by playker View Post
It's possible that not all Air applications will work on Linux, even with the official runtime and launcher, but at least people have the choice to try more than one method.
Fair enough and now they have yet one more!
 
Old 01-07-2019, 05:46 AM   #20
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
Quote:
Originally Posted by playker View Post
Using these tools has this advantage over custom installers that you can see the list of installed files and the installation scripts.
But this is also true of making a native (Slackware) package and the entire list of files and installation scripts is in the same location as every other native package.

Quote:
Originally Posted by playker View Post
I agree with the Slackware advice to check the files and scripts when installing an rpm.
That is slightly harder to do when the rpm is created on the fly and deleted after install as is the case with air apps. You can't really inspect them before they are installed since they do not yet exist.

Last edited by ruario; 01-07-2019 at 06:21 AM.
 
Old 01-07-2019, 07:48 AM   #21
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
As a side note, for anyone wanting to know how I worked out the layout and the fact that ‘/opt/Adobe AIR/Versions/1.0/Resources/appentry’ is the stub launcher. I did it by installing e-Deklaracje in a separate Linux VM using the normal AIR install method. I made use of the shell script mentioned at the top of this gist to see where all the files had been placed. I compared the list of installed files with the list of files found inside e-deklaracjedesktop.air. The obvious one I could not immediately account for was the small executable/launcher. I then ran an md5sum on on this file and did a recursive md5sum (by way of find) on all the files included in a directory containing an extracted AdobeAIRInstaller.bin. This showed me the match was ‘appentry’. I then uninstalled e-deklaracjedesktop and tried placing all the files manually (bar those needed for desktop integration). This worked. I then threw away the VM and created a new clean 32-bit Slackware VM and tried out the manual steps again and that also worked.

Last edited by ruario; 01-07-2019 at 07:49 AM.
 
Old 01-07-2019, 08:13 AM   #22
playker
LQ Newbie
 
Registered: Nov 2009
Location: Poland
Distribution: Slackware 14.2
Posts: 18

Original Poster
Rep: Reputation: 8
ruario thanks for going through the effort with e-deklaracje. I think your method is good, because it uses the correct upstream package (AdobeAIRInstaller.bin) and (as far as I can understand) it uses the correct application launcher and installs all files in the right location. IMO much better than the method from AUR in Arch. With a little work a slackbuild for Adobe Air could be made, and perhaps a program/script such as "airinst" or similar which takes an .air file as argument and installs it on the system.

Quote:
Like the SDK trick, this is a truly cross distro method as no rpm is required, as you stated was your original goal.
Just to say that the rpm tool can be installed on other distributions and doesn't have to be used except in special cases, Adobe Air is one such case.
 
Old 01-07-2019, 08:30 AM   #23
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
Quote:
Originally Posted by playker View Post
(as far as I can understand) it uses the correct application launcher
Actually I didn't place any Desktop Environment launchers (/usr/share/icons/hicolor/*.desktop files), system wide icons (that go under /usr/share/icons/hicolor) or mime configuration files (/usr/share/mime/). It seems that in the case of the AIR runtime and apps, this is normally done in post install of the rpm/debs that are made on the fly. So any SlackBuild(s) would need to handle that. It is a fairly trivial thing to do but since I was only testing and was happy to launch from the terminal I didn't put the effort in.

Quote:
Originally Posted by playker View Post
perhaps a program/script such as "airinst" or similar which takes an .air file as argument and installs it on the system.
I think a better option would be a SlackBuild for each air file that people care about. There can't be many left as it is a dying package type AFAICT or perhaps a generic air2tgz script that takes any .air package and turns it into a .tgz Slackware package (that wouldn't be much more effort since the layout for each .air file is basically the same).

Having native packages for the AIR runtime and all AIR-based applications would ensure that everything is tracked in the normal Slackware package logs, which is optimal IMHO.

Quote:
Originally Posted by playker View Post
Just to say that the rpm tool can be installed on other distributions
I do realise this and have done it many times myself for various reasons, mainly related to Opera and Vivaldi package testing as part of my day job. I just think that it is generally a pretty bad idea and should be avoided whenever possible. Some of the stuff that is done in rpm post install scripts is completely inappropriate on Slackware. In addition since rpm packages are generally configured to place files directly into directories like /usr, it is easy to overwrite files. On a real rpm-based distro this isn't an issue because the package manager is normally aware of all files within /usr anyway and thus will notice conflicts.

Also, installing rpm can be easy on some (most) distros and a complete pain on others, particularly specialist (or tiny) distros that do not have a good range of dependencies and/or development tools available.

Last edited by ruario; 01-07-2019 at 09:05 AM. Reason: clarified about desktop integration
 
1 members found this post helpful.
Old 01-07-2019, 04:00 PM   #24
bassmadrigal
LQ Guru
 
Registered: Nov 2003
Location: West Jordan, UT, USA
Distribution: Slackware
Posts: 8,792

Rep: Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656
Quote:
Originally Posted by ruario View Post
Dugan's solution is probably best because you will get a more recent version of Air. Failing that, I still don't think installing an rpm on Slackware directly is a good idea and can be avoided. Just extract the contents of the archive instead.

Switch to an empty working directory and fetch the binary.

Code:
$ wget http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRInstaller.bin
The .bin actually has a .tar.lzma archive inside it. You just need to find it. Grep can help you do that e.g. (assuming bash)

Code:
$ LC_CTYPE=C grep -abom1 ]$'\000\000'....$'\377\377\377\377\377\377' AdobeAIRInstaller.bin 
6704:]???????
Add 1 to this value (e.g. 6705). The contents of the internal, compressed tar can be extracted like so:

Code:
$ tail -c+6705 AdobeAIRInstaller.bin | xz -qqd | tar xv
--snip--
You can move the files under the build directory into place or create a .SlackBuild to automate all of this and allow you to easily uninstall at a later date.
Since you went into detail on how you figured out the launcher, can you explain what that grep command does? I figured this was some sort of tarball within a script, but I had no idea how to go about figuring it out.
 
Old 01-08-2019, 02:16 AM   #25
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
Quote:
Originally Posted by bassmadrigal View Post
Since you went into detail on how you figured out the launcher, can you explain what that grep command does? I figured this was some sort of tarball within a script, but I had no idea how to go about figuring it out.
Sure, happy to! The key to finding a compressed archive within another file is usually to search for the magic number of the file format used to compress the archive. As it happens LZMA is not a true file format but rather a compressed stream, so it does not really have a proper magic number. Nonetheless, there is a recognisable pattern to the start of a stream. I worked out the pattern years ago, just by compressing a bunch of files and looking at their start in hexdump.

This is what the start of a typical LZMA stream looks like in hex. I'll use ?? to symbolise a character that might vary:

Code:
5d 00 00 ?? ?? ?? ?? ff ff ff ff ff ff
That pattern is not a perfect match for every possible LZMA stream. For example when LZMA performs compression on a RISC processor (like PowerPC) all of those trailing ffs would become 00s but it is good enough for the vast majority of LZMA compressed archives you are likely to encounter.

For my grep search I made use of bash's ability to print non ASCII characters when represented as Octal inside $'', e.g. $'\377' is 'ff'. The LC_CTYPE=C at the start is to force grep to treat all character that make up the search in thier raw form. Then the grep options break down as follows:

-a = Process a binary file as if it were text (needed, otherwise you will just get a "binary file matches" message)
-b = Print the 0-based byte offset (this is how we find the position)
-o = Print only the matched parts (in combination with -b, this means that it should print the offset of the matching part itself, rather than a 'line' which would be meaningless here)
-m = Stop reading a file after X matches (I defined '1', so only the first match is printed, lessening the chance of false positives)

The way this all works is very tied to GNU grep specifically. You can do similar tricks on other UNIX-like OSes then you will need to use different tools (e.g. "perl -ln0777e 'print (pos() - 13) while /]\x00{2}.{4}\xff{6}/g' AdobeAIRInstaller.bin").

(Side note: On Slackware, GNU grep is compiled with support for Perl style regular expressions (-P) directly, so I could have also done it like this "grep -Pabom1 ']\x00{2}.{4}\xff{6}' AdobeAIRInstaller.bin". That would have made the search less reliant on bashisms but on the flip side it would work on fewer distros, since GNU grep is not always compiled with Perl style regex support.)

Now you have the position where the match begins (6704) but remember that grep gives a '0-based byte offset'. Thus you need to add 1, giving you 6705. Once you have this position you can use tail's -c to force it to work with bytes. The + (i.e. "+6705") then causes it to start outputting with byte 6705 (i.e. the start of the LZMA compressed archive).

At this point I could just pass it straight to tar with -J (which handles both LZMA and XZ compression) but when doing tricks like this I normally prefer to send the file to xz first because they often have trailing bytes after the end of the compressed archive. If I give xz two '-q' switches (in addition to the '-d' that causes decompression), it will be really quiet and not even display errors when it hits the end of the compressed stream (it'll just exit). Thus I can pass a 'clean', decompressed archive through the pipe to tar.

So that is the explanation. Now for a little history. I learnt all this back in 2012 when I was playing around on a machine with no RPM utilities and needed to extract the contents of some rpms. So I wrote my own rpm2cpio in less than 10 lines of shell script. Here is my old blog post (thanks to archive.org!). I have since tweaked that rpm2cpio to use LC_CTYPE=C (instead of LANG=C, which is not always enough) and moved it to github as a gist. As it happens the search listed in the rpm2cpio example ('.7zXZ\|]'$'\000\000''....'$'\377\377\377\377\377\377''\|BZh9\|'$'\037\213\b') is what I actually performed as I did not know the compression type of the tar archive (or even for certain there was a compressed archive) within the .bin installer before I looked for it. So in my above example, I just gave a simplified grep search.

Finally, just one more thing to consider if you ever happen to need an rpm2cpio on another distro. These days you can typically simplify things further, as I note in the comments on that gist:

Quote:
These days, packages are almost exclusively XZ compressed on recent versions of RPM-based distributions. If you only need to handle files from modern versions of Fedora, SUSE, etc. then you can get away with a single line of POSIX shell:

Code:
#!/bin/sh
tail -c+`grep -Fabom1 7zXZ "$1" | cut -d: -f1` "$1" | xz -d
You will note that I don't add 1 to the result. This is because the XZ magic number actually starts 'fd' (in hex). By leaving off the first character I simplify the search (no need for LC_CTYPE=C or bashisms) and I get the bonus of not needing to do any math. Oh and in case you are wondering, I use `` style, rather than $() in that example, just to make it one character shorter. Hey, don't judge me as it is supposed to be minimal after all!
 
2 members found this post helpful.
Old 01-08-2019, 02:59 AM   #26
playker
LQ Newbie
 
Registered: Nov 2009
Location: Poland
Distribution: Slackware 14.2
Posts: 18

Original Poster
Rep: Reputation: 8
Quote:
Originally Posted by ruario View Post
Actually I didn't place any Desktop Environment launchers
I meant the correct Air application launcher, the executable copied to /opt/edeklaracje/bin/edeklaracje for example. Yes, in the rpm postinstall script a .desktop file is installed too. The script can be read with "rpm -q --scripts". When using "airwrap" on Slackware I got an icon for e-Deklaracje on the desktop and in the applications menu under Accessories and I used them to launch the application.

Quote:
I think a better option would be a SlackBuild for each air file that people care about.
It's no good if you can't install an .air file downloaded from the Internet. For example when there is a message that a new version is available, the updater won't work but you should be able to go to the website, download the new version and install it easily. air2tgz/air2txz would be fine.
 
Old 01-08-2019, 03:21 AM   #27
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
Quote:
Originally Posted by playker View Post
I meant the correct Air application launcher, the executable copied to /opt/edeklaracje/bin/edeklaracje for example.
Ah yes, indeed it is the 'correct' (normal) launcher (I guess I misunderstood you before). By the way, I think for the real one it used the naming /opt/e-Deklaracje/bin/e-Deklaracje (IIRC) but since the naming didn't seem to matter so much (just relative positions to the rest of the files, I simplified it to edeklaracje in my example above).


Quote:
Originally Posted by playker View Post
It's no good if you can't install an .air file downloaded from the Internet. For example when there is a message that a new version is available, the updater won't work but you should be able to go to the website, download the new version and install it easily. air2tgz/air2txz would be fine.
Perhaps but if it is a 'normal' SlackBuild it could be placed on SBo and the maintainer could update update the SlackBuild for any new version. But I agree with you air2tgz/air2txz is probably easier given the layout of air files is very predictable. So yeah, just one script to handle all .air files is less to maintain.

Last edited by ruario; 01-08-2019 at 03:57 AM.
 
Old 01-08-2019, 02:56 PM   #28
bassmadrigal
LQ Guru
 
Registered: Nov 2003
Location: West Jordan, UT, USA
Distribution: Slackware
Posts: 8,792

Rep: Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656Reputation: 6656
Thanks for the great and hugely informative post, Ruarí! I definitely learned some stuff I didn't know (even if I eventually forget it again).
 
Old 01-09-2019, 04:19 AM   #29
ruario
Senior Member
 
Registered: Jan 2011
Location: Oslo, Norway
Distribution: Slackware
Posts: 2,557

Rep: Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761Reputation: 1761
@bassmadrigal: Thanks, very kind of you. I have learnt plenty of stuff from you over the years, so happy to return the favour.
 
2 members found this post helpful.
Old 04-05-2020, 06:41 AM   #30
camelinio451
LQ Newbie
 
Registered: Mar 2020
Posts: 3

Rep: Reputation: 3
Quote:
Originally Posted by average_user View Post
Anyway, I don't use e-deklaracje anymore these days as they started to provide pre-filled reports and you only need a web browser to access them. It was a bad idea to use Adobe Air in the first place, Adobe stopped supporting Linux in 2011.
This is the best way, but if you have 0 PLN of over-payment/due you cannot login. And this was my case this year, so I decided to try with e-Deklaracje app.


I will show step by step how did I run e-Deklaracje on my 64-bit Slackware with wine.

1) Prepare your system for running 32-bit applications with this guide: https://docs.slackware.com/slackware:multilib

2) Install wine. Default installation is 32-bit. I turned on also 64-bit option in Slackbuild. It is only for potential future needs. It is not necessary now.
Code:
WIN32=${WIN32:-yes}
WIN64=${WIN64:-yes}
3) Install winetricks.

4) Using winetricks create new wineprefix folder. Use any name you want. It’s quite long story what is wineprefix and why we use it, so if you want know more look at guide and FAQ for wine.

5) Using wine, install Adobe Reader in your wineprefix folder.
Code:
export WINEPREFIX=~/.local/share/wineprefixes/your-wineprefix-folder
wine winecfg
wine ~/Desktop/AdbeRdr950_en_US.exe
6) Using winetricks, install Adobe AIR in your wineprefix folder. Installer gave me error message, but AIR was installed properly anyway.

7) Download e-Deklaracje app to your virtual C: drive.
Code:
cd ~/.local/share/wineprefixes/your-wineprefix-folder/drive_c
wget http://www.e-deklaracje.gov.pl/files/dopobrania/e-dek/app/e-DeklaracjeDesktop.air
8) Using AIR, install e-Deklaracje app.
Code:
cd ~/.local/share/wineprefixes/your-wineprefix-folder/drive_c/Program\ Files/Common\ Files/Adobe\ AIR/Versions/1.0/Resources
wine airappinstaller.exe c:\\e-DeklaracjeDesktop.air
9) At this point you should be able for run e-Deklaracje app.
Code:
cd ~/.local/share/wineprefixes/your-wineprefix-folder/drive_c/Program Files/e-Deklaracje
wine e-Deklaracje.exe
Choose now your tax form, fill it, sign and send. After that you can download confirmation in “My settlements” (“Moje rozliczenia”).
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: Improving the Linux Ecosystem from Within: Thoughts on Adobe Axing Adobe Air for Linux LXer Syndicated Linux News 0 06-19-2011 08:30 AM
LXer: Install Adobe AIR and 10 Air Applications on Ubuntu 8.10 LXer Syndicated Linux News 0 12-20-2008 07:01 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware

All times are GMT -5. The time now is 08:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration