Has properties webscript

I did some other java based webscript. From portlet flash application I need to get information about some user's permissions on object specified by nodeRef. So firstly I tried to do this via JavaScript based webservice, but there are no tools to do this.

I did some other java based webscript. From portlet flash application I need to get information about some user's permissions on object specified by nodeRef. So firstly I tried to do this via JavaScript based webservice, but there are no tools to do this.

 First thing is to create description xml for this service:

 <webscript>
  <shortname>hasRights</shortname>
  <description>Returns some amazing info ;-)</description>
  <url>/archivace/hasrights?u={userName}&amp;s={nodeRef}&amp;p={permissionName}</url>
  <format default="xml"/>
  <authentication>user</authentication>
  <transaction>required</transaction>
</webscript>

As you can see, there are three parameters: u, which specifies userName of user, of which we want to get this information. Parameter  s, which specifies nodeRef of node and finally p, which is optional and specifies one of permissions. If not set, WriteContent permission is used.

Space permissions:

  • ReadProperties
  • ReadChildren
  • WriteProperties
  • DeleteNode
  • DeleteChildren
  • CreateCildren

Content permissions:

  • ReadContent
  • WriteContent
  • ReadProperties
  • WriteProperties
  • DeleteNode
  • ExecuteContent
  • SetOwner

You can find a complete list of all permisions in tomcat/webapps/alfresco/WEB-inf/classes/alfresco/model/permissionDefinitions.xml.

 Now let's write some javacode: I created a class HasRights, which extends AbstractWebScript. Let's have a look into that code

 public class HasRights extends AbstractWebScript{
    private AuthenticationComponent authenticationComponent;
    private PermissionService permissionService;

    public void execute(WebScriptRequest req, WebScriptResponse res)throws IOException {
        try{
            HttpServletRequest httpReq = ((WebScriptServletRequest)req).getHttpServletRequest();
            String spaceRef = "workspace://SpacesStore/" +
              (String)httpReq.getParameter("s");
            String userName = (String)httpReq.getParameter("u");
            String permission = (String)httpReq.getParameter("p");
            if(permission==null)
                permission = "WriteContent";

In case of this webScript is called method execute is the first to run (not exactly, setters of this class are called sooner – setAuthenticationComponent() and setPermissionService()) . In this method javax.servlet.http.HttpServletRequest is used for get parameters.

            NodeRef nodeRef = new NodeRef(spaceRef);
            Node noda = new Node(nodeRef);
            this.authenticationComponent.setCurrentUser(userName);

In those steps Node and nodeRef objects are created and currently logged user is setted to wanted user.

res.setContentType("text/xml");
res.getWriter().write("<hasRightsResponse>");
res.getWriter().write("<nodeName>"+noda.getName()+"</nodeName>");
res.getWriter().write("<nodeRef>"+nodeRef.toString()+"</nodeRef>");
res.getWriter().write("<userName>"+this.authenticationComponent.getCurrentUserName()+"</userName>");
res.getWriter().write("<permissionName>"+permission+"</permissionName>");
res.getWriter().write("<hasPermission>"+this.permissionService.hasPermission(nodeRef, permission)+"</hasPermission>");
res.getWriter().write("</hasRightsResponse>");

After all that a response is printed out. Example of output is following:

<hasRightsResponse>
    <nodeName>sezeni001.xml</nodeName>
    <nodeRef>workspace://SpacesStore/da5ad5b0-3bc4-4d4c-88fe-4f9cf4f349f5</nodeRef>
    <userName>pepik1</userName>
    <permissionName>WriteContent</permissionName>
    <hasPermission>DENIED</hasPermission>
</hasRightsResponse>

I forgot to mention the most importatn step – to define a bean with this webscript. So it looks like this (in web-scripts-application-context.xml):

 <bean id="webscript.org.alfresco.archivace.hasrights.get" class="cz.shmoula.webscripts.HasRights" parent="webscript">
      <property name="authenticationComponent" ref="AuthenticationComponent"/>
      <property name="permissionService" ref="PermissionService"/>
  </bean>

And that's it, pretty simple ;-).

Libisemi, tvorba bookmarkletu

Pro potřeby libisemi, "prvního asociálního sociálního serveru" jsem potřeboval vytvořit bookmarklet. Protože to však nešlo udělat jednoduše, jako odeslání adresy pomocí GETu, protože na straně serveru používám framework CakePHP a v něm user friendly URLs ve formátu http://domain/controller/action/param. V tomto případě bych jako parametr nemohl předat http adresu. Z toho důvodu jsem byl nucen poslat tuto informaci metodou POST. A když už takto, tak rovnou asynchronně a počkat si na výsledek. V tomto postu bych se chtěl podělit o získané zkušenosti vzniklé na základě vyřešení vzniklých problémů.

Pro potřeby libisemi, "prvního asociálního sociálního serveru" jsem potřeboval vytvořit bookmarklet. Protože to však nešlo udělat jednoduše, jako odeslání adresy pomocí GETu, protože na straně serveru používám framework CakePHP a v něm user friendly URLs ve formátu http://domain/controller/action/param. V tomto případě bych jako parametr nemohl předat http adresu. Z toho důvodu jsem byl nucen poslat tuto informaci metodou POST. A když už takto, tak rovnou asynchronně a počkat si na výsledek. V tomto postu bych se chtěl podělit o získané zkušenosti vzniklé na základě vyřešení vzniklých problémů.

Začnu nejprve rozhraním na straně serveru. Dovolím si vypustit zbytečnosti a defakto celý zápis zobecnit. Vzhůru tedy do Controlleru. Následující funkce (vlastně spíš metoda, protože je umístěna ve třídě rozšiřující AppController, jen mi tohle vznostné oslovení u PHP nesedí ;-)) přijmě data zaslaná (asynchronně) pomocí metody post a pustí se do zpracování, které předá zobrazovací vrstvě.

function addajax(){
    // prijeti dat
    $formular = $this->params['form'];
    $url = $formular['url'];
      
    // vystupni layout chci xml a nechci zobrazovat debug informace
    $this->layout = 'xml';
    Configure::write('debug',0);
   
    /*
     * Dalsi akce, jako je napr. parsovani ziskaneho dokumentu
     */
       
    // zapsani informaci a ulozeni do session
    $output[0]['url'] = $url;
       
    $this->Session->write('toSave',$innerHTML);
    $sessId = $this->Session->id();
       
    // zapisu jeste cislo session
    $output[0]['sessionId'] = $sessId;
    // a cele pole predam vrstve View
    $this->set('output', $output);
}

 Uvnitř předcházející metody vyžaduju zobrazení v layoutu xml, ten je definován následujícím způsobem, který mi vygeneruje dokument typu text/xml, zapíše do něj záhlaví a vloží vlastní strukturu, která je generovaná uvnitř vrstvy View. Celkový výstup je uveden na výpisu níže.

<?php
    header('Content-type: text/xml');
    echo $xml->header();
?>
<addInfo>
<?php echo $content_for_layout; ?>
</addInfo>

Další činnost prováděná uvnitř metody v Controlleru je vytvoření pole "output", které je předáno vrstvě View. Do prvního prvku tohoto pole ještě přidám požadované url (index "url"), celou tuto konstrukci uložím do session a následovně do toho stejného pole přidám i číslo této session (index "sessionId"). Samotný výstup v podobě XML je generován ve view, kterému předávám data pomocí posledního řádku ve výpisu kontrolleru. View je zhruba následující:

echo $xml->elem('sessId',null,$output[0]['sessionId']);
echo $xml->elem('url',null,$output[0]['url']);
. . .

Tato konstrukce za pomocí helperu Xml vygeneruje tagy sessId a url a vloží do nich dané hodnoty. Výstupem je potom následující XML, které je odesláno zpět skriptu na straně prohlížeče (klienta), který provedl volání.

<?xml version="1.0" encoding="UTF-8" ?>
<addInfo>
    <sessId>4f40061d6ffa5e6a4a8f4b64b79eb4d3</sessId>
    <url>http://domain/page.htm</url>
</addInfo>

Bookmarklet jsem definoval konstrukcí tzv. anonymní funkce – void((function(){ . . . }()), který provede kód umístěný vevnitř. Tímto kódem vytvářím nový element "script", který připojím ke stávající stránce.

 javascript:
    void((
        function(){
            var element=document.createElement('script');
            element.setAttribute('src','http://www.libisemi.cz/send.js');
            document.body.appendChild(element);
            var http=getHttp();
            sendPost(http,encodeURIComponent(location.href));
        }()
    )

Tento skript sestává z metody, která na základě typu prohlížeče vygeneruje tzv. HttpRequest objekt, který je použit pro připojení k serveru a odeslání dat. V prohlížečích Netscape Navigator, Apple Safari a Firefoxu se tento objekt vytváří pomocí konstruktoru objektu XMLHttpRequest(), který je součástí objektu window, takžestačí otestovat jeho existenci. Microsoft samozřejmě musí mít něco extra, takže tento objekt vytváří pomocí ActiveX komponenty, takže pokud nevyjde první testování, otestuju existenci ActiveXObject komponenty. Pokud ani tohle testování nevyjde, ohlásím chybu a uživatel má smůlu.

function getHttp(){
    var http = false;
   
    if(window.XMLHttpRequest){
        http = new XMLHttpRequest();
    }else if(window.ActiveXObject){
        http = new ActiveXObject("Microsoft.XMLHTTP");
    }else alert("nejde vytvorit request!");
   
    return http;
}

Vytvořený HttpRequest objekt předám  funkci, která pomocí něj metodou POST odešle data na server. Pomocí metody onReadyStateChange je ještě nastavena další anonymní funkce, která testuje přijatou odpověď serveru – stav požadavku (readyState), kdy čeká na požadavek, až je kompletní a současně na stavový kód protokolu HTTP 200 – OK. Pokud tato skutečnost nastane, pokračuje ve zpracování, rozparsuje přijaté xml a přesměruje stávající dokument na novou adresu, ke které přiloží získané informace (v tomto případě číslo session, které vygeneroval server na základě přijatých dat POST metodou). Jedná se o jednoduchý AJAX, spousta dalších informací se válí volně na síti, nebo někde v archívu mého blogu.

function sendPost(http,url){
    http.open("POST","http://www.libisemi.cz/addajax");
    http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Connection","close");
    http.onreadystatechange = function(){
        if(http.readyState == 4 && http.status == 200){
            var response = http.responseXML;
            // … parsovani odpovedi a ziskani promenne 'id' – cislo session
            window.location = "http://www.libisemi.cz/addform/"+id;
        }
    }
    http.send("url="+url);
}

 Tímto způsobem je vytvořen (polo-)funkční bookmarklet, který funguje po druhém kliknutí a pouze na stejné doméně. Nemám ale rád polovičatá řešení, tak už mám rozdělané řešení. Tohle bych si ale dovolil popsat až příště, tenhle post mi připadá už dost dlouhý ;-).

Hacking Android III

Dalším krokem je vytvoření "virtualního harddisku", na který budu postupně přesouvat jednotlivé Androidí komponenty. Jedná se o soubor, ve kterém jsou "čtyři partišny" naformátované souborovým systémem ext3. V tomto kroku využívám virtuálního stroje v podobě v qemu běžícího Damn Small Linuxu, který jako disk využívá právě onen "virtuální disk". Ale popořádku.

Dalším krokem je vytvoření "virtualního harddisku", na který budu postupně přesouvat jednotlivé Androidí komponenty. Jedná se o soubor, ve kterém jsou "čtyři partišny" naformátované souborovým systémem ext3. V tomto kroku využívám virtuálního stroje v podobě v qemu běžícího Damn Small Linuxu, který jako disk využívá právě onen "virtuální disk". Ale popořádku.

Nejprve vytvořím prázdný soubor o velikosti cca 5*128MB, konkrétní rozpis bude následovat.

 1. $ dd if=/dev/zero of=disk ibs=1024 count=655360

 Potom s tímto diskem nabootuju DSL pomocí qemu

 2. $ qemu -hda disk -cdrom dsl.iso -boot d

V tomto virtuálním stroji potom fdiskem rozdělím tento disk, abych měl na první oblasti sloužící jako root bylo 128M, na druhé, která bude sloužit jako swap/cache bylo taky 128M, na třetí se bude nacházet samotný systém a mělo by postačovat 256M a zbytek bude pro uložení uživatelských dat.

Teď je nutné oblasti naformátova a přidat jurnal (taky uvnitř DSL)

3. $ mkfs.ext2 /dev/hda{1 | 2 | 3 | 4}

4. $ tune2fs -C 1 -L {root | cache | system | user} -j /dev/hda{1 | 2 | 3 | 4}

Dalším krokem je instalace boot loaderu – GRUBu. Na této jednoduchosti jsem zůstal docela dlouho "viset", protože jsem neprováděl dostatečně "RTFM" :-D. Aneb jednoduše řečeno, používal jsem grub-install nacházející se v DSL, ovšem jedná se o verzi 0.91, takže jsem pokaždé končil s hláškou "No setup signature found…". Až jsem si opravdu přečetl jediný thread, bylo jasno a do boot/grub putovaly soubory z verze 0.97. A najednou, všechno v pořádku! Ale pěkně popořadě: první oblast, označenou jako root, využiju i pro umístění adresáře se soubory potřebnými pro zavedení systému – boot. Pro zjednodušení použiju grub-install (musí se jednat o onu verzi 0.97 a vyšší, pokud je použito distribuční jádro dodávané s Androidem – 2.6.27) uvnitř DSL, hda1 je připojeno na /mnt/hda1.

5. $ grub-install –root-directory=/mnt/hda1 –recheck /dev/hda

Teď je potřeba upravit menu.lst a nahrát soubory s jádrem a ramdisk. Obsah mého souboru menu.lst je na následujícím výpisu.

default 0
timeout 10
title Android
root (hd0,0)
kernel /boot/kernel
initrd /boot/ramdisk.img

 Tyto soubory však mám zatím pouze uvnitř mého installer.img, případně v adresáři mydroid/out/target/product/eee_701. Pro jejich přenesení používám namountování mého virtuálního disku pomocí offsetu. Nejprve musím zjistit, kde jednotlivé oddíly začínají. K tomu použiju fdisk uvnitř DSL:

Image Hosted by ImageShack.us

 Offset vypočítám, když vynásobím počáteční sektor 512. Offset prvního oddílu je tedy 63*512=32.256. Tento oddíl teď můžu připojitjako loopback zařízení a zkopírovat do adresáře boot soubory  kernel a ramdisk.

6. $ mount -t ext3 -oloop,offset=32256 disk /mnt/hda1
7. $ cp  ~/mydroid/out/target/product/eee_701/kernel /mnt/hda1/boot
8. $ cp ~/mydroid/out/target/product/eee_701/ramdisk.img /mnt/hda1/boot

Teď je možné disk odpojit a nabootovat jádro pomocí qemu. Nedostaneme ovšem shell, protože tu zatím nejsou nahrané žádné soubory.

9. $ umount /mnt/hda1
10. $ flush
11.  $ qemu -hda disk

Image Hosted by ImageShack.us

 

 

Hacking Android II

Uvízl jsem na mrtvém bodě a nemožnosti vytvořit ramdisk, stejně tak mi nejde do hlavy jakási nekompatibilita mezi jednotlivými verzemi gzipu. Aneb zřejmě nebootuju, alespoň ne způsobem, který by měl fungovat.

Uvízl jsem na mrtvém bodě a nemožnosti vytvořit ramdisk, stejně tak mi nejde do hlavy jakási nekompatibilita mezi jednotlivými verzemi gzipu. Aneb zřejmě nebootuju, alespoň ne způsobem, který by měl fungovat.

Ztroskotal jsem na snaze vytvořit vlastní initrd z ramdisku vytvořeného automaticky při sestavování Androida. Vytvořený ramdisk.img je archiv vytvořený pomocí cpio, tak jsem si řekl, že nejjednodušší bude jej rozbalit, poupravit a znovu zabalit. Logické, jednoduché…

1. $ mkdir ramdisk && cd ramdisk

2. $ zcat ../ramdisk.img | cpio -i

teď mám rozbalenou adresářovou strukturu, neudělám žádný zásah a zabalím zpět

3. $ find . -print | cpio -o > ../ramdisk2.img

4. $ cd .. && gzip ramdisk2.img && mv ramdisk2.img.gz ramdisk2.img

…ale bohužel nefunkční pro bootování, soubory nejsou totožné.

Image Hosted by ImageShack.us

Už hlavička (resp. začátek) je okem rozeznatelný – původní ramdisk začíná čísly, ve druhém vytvořeném ramdisku je znatelná struktura filesystému. OK, projdu si make soubory a zjistím, jak je to baleno. Ještě před tím jsem ale vyzkoušel, soubor ramdisku gzipem rozbalit a znovu zabalit. OUHA – rozdílné! Pokud ovšem rozbalím obsah a hned jej skrze rouru zase zabalím, tak jsou totožné, viz následující výpis:

$ zcat ramdisk.img > ramdisk

$ gzip ramdisk

$ ls -la ramdisk* && diff ramdisk.img ramdisk.gz

Image Hosted by ImageShack.us

$ zcat ramdisk.img | gzip > ramdisk2.img

v tomto případě jsou už stejné

Tímto způsobem vytvořený (rozbalený a znovu zabalený pouze gzip archiv) ramdisk jde bez problémů použít pro nabootování (narozdíl od rozbaleného kompletního archivu pomocí cpio).

$ qemu -kernel kernel -initrd ramdisk2.img -hda /dev/zero

SOLVED – problém je v parametrech!

Stačilo si přečíst dokumentaci k jádru ( kernel/Documentation/initrd.txt) a upravit parametry. Takže už se nedivím onomu pověstnému RTFM!

rozbalení:

$ gzip -cd  ../ramdisk.img | cpio -imd

zabalení:

$ find . | cpio -H newc -o | gzip -9 -n > ../ramdisk2.img

Nepoužitá možnost tvorby initrd

Resp. použitá, ale taky nefungovala, takže jsem vděčný za informaci o těch parametrech. Každopádně následující informace by se mohly v budoucnu taky hodit, proto si je sem poznamenám. Jedná se o vytvoření prázdného souboru, vytvoření filesystému v něm a jeho připojení pomocí loopback zařízení. Tento postup je detailně popsán v návodu na tvorbu LiveCD distribuce Gentoo.

$ touch initrd
$ dd if=/dev/zero of=initrd bs=1024k count=8
$ losetup /dev/loop0 initrd
$ mke2fs /dev/loop0
$ mkdir /media/initrd
$ mount /dev/loop0 /media/initrd 

Pak vytvořit adresářovou strukturu

$ cd /media/initrd
$ mkdir etc dev lib bin proc new cdrom

A některá základní zařízení

$ cd dev
$ mknod console c 5 1
$ mknod null c 1 3
$ mknod hda b 3 0
$ mknod hdb b 3 64
$ mknod tty c 4 0
$ mknod loop0 b 7 0 

V dalším kroku je nutné vytvořit init skript a nahrát základní systémové nástroje, případně využít BusyBox.

Hacking Android I

Tak jsem si slibil, že si zkusím pohrát s Androidem a ideálně jej dostanu do ps3. To samozřejmě až v nějaké další části, nejprve se zkouším dostat do obrazu a rozjet jej alespoň na x86 platformu. Nějaký částečný success už jsem utrpěl, ovšem jsou tu i  "drobnosti", které mi zatím dělají problémy. Každopádně to zkusím postupem času shrnovat v blogpostech.

Tak jsem si slibil, že si zkusím pohrát s Androidem a ideálně jej dostanu do ps3. To samozřejmě až v nějaké další části, nejprve se zkouším dostat do obrazu a rozjet jej alespoň na x86 platformu. Nějaký částečný success už jsem utrpěl, ovšem jsou tu i  "drobnosti", které mi zatím dělají problémy. Každopádně to zkusím postupem času shrnovat v blogpostech.

Vyšel jsem z verze pro Asus eee, protože si myslím, že přece jenom x86 je x86 a poupravit existující konfiguraci jádra, na kterém Android bez problémů běhá, bude jednodušší, než tvořit config na zelené louce. Takže jsem si vytvořil ve VirtualBoxu novou mašinu a nainstaloval Kubuntu (2.6.24-22-generic). Androuš má krásně popsaný postup, jak stáhnout zdroje z repozitáře pomocí GITu.Protože se netahá "master" větev, je nutné spustit inicializace repozitáře s parametrem a ručně vytvořit lokální manifest.

1. $ mkdir ~/mydroid

2. $ cd mydroid

3. $ repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake

4. $ repo sync

cat > ./.repo/local_manifest.xml << _EOF
<manifest>
      <project name="platform/vendor/asus/eee_701" path="vendor/asus/eee_701"/>
</manifest>
_EOF

5. $ repo sync

V tomto okamžiku by měly být staženy kompletí zdrojové kódy (resp. ty jsou staženy už  krokem čtyři, krok pět stáhne patch pro eee verzi) , v mém případě s jádrem 2.6.27 (podadresář kernel) a moduly, init skripty a konfigurací jádra pro Asus eee (podadresář vendor/asus/eee_701). Pak je možné už jednoduše kompilovat pomocí make, po specifikaci parametrů pomocí proměnných.

6. $ TARGET_ARCH=x86 TARGET_PRODUCT=eee_701  DISABLE_DEXPREOPT=true make

7. $ TARGET_ARCH=x86 TARGET_PRODUCT=eee_701  DISABLE_DEXPREOPT=true make bootimage userdataimage

8. $ TARGET_ARCH=x86 TARGET_PRODUCT=eee_701  DISABLE_DEXPREOPT=true make installer_img

 Buildovací proces vygeneruje jednotlivé "images" v podadresáři out/target/product/eee_701, installer_img potom vygeneruje installer.img, kde jsou zabaleny všechny tyto obrazy a je možné jej nabootovat (např. pomocí qemu), ovšem nabootuje pouze z boot partition (boot.img) a nepřipojí kořenový systém, takže naběhne pouze sh, který ovšem vůbec nic neumí.

9. $ qemu -hda installer.img

Image Hosted by ImageShack.us

Image Hosted by ImageShack.us

Teď se snažím o vytvoření obrazu, který mi kompletně nabootuje Androuše, ale o tom příště!

Android do ps3?

Venturebeat.com dostali Android na Asus EEE, takze uz klonuju Kubuntu na VirtualBoxu, syncuju svn a zkusim to zbuildovat na ppc a nahrat na ps3 ;-). Takovej krasnej jednoduchej tutec (pro x86) jsem nasel treba tu

Venturebeat.com dostali Android na Asus EEE, takze uz klonuju Kubuntu na VirtualBoxu, syncuju svn a zkusim to zbuildovat na ppc a nahrat na ps3 ;-). Takovej krasnej jednoduchej tutec (pro x86) jsem nasel treba tu