robert.schöbel.net

Outlook holt Mails doppelt ab

May 9th, 2010

Problem:

Outlook 2007 verschiebt Mails von gmx doppelt und dreifach in einen Postfach Ordner

bzw.  es sieht so aus als ob es die Mails mehrfach abholt

Lösung:

Es waren mehrere Regeln für ein Postfach angelegt

z.B.:  nach Erhalt einer Nachricht über das Konto xy@gmx.net diese in Ordner xy verschieben

und Nach erhalt einer Nachricht von xyz@gmx.net diese in Ordner xy verschieben

Um das Problem zu lösen muss man eine dieser beiden Regeln löschen.

Robert Schöbel | usefull stuff | No comments Jump to the top of this page

Dompdf Memory Error

April 12th, 2010

Folgendes Problem beim Export von PDF-Dateien mit Dompdf
{code type=TEXT}
Fatal error: Allowed memory size of xxxxxx bytes exhausted (tried to allocate xxxxxxxx bytes) in /var/www/vhosts/domain.net/httpdocs/itpage/system/application/libraries/dompdf/lib/class.pdf.php(1969) : eval()’d code on line 5914
{/code}

Lösung (nicht die Beste Lösung)
öffen die Datei:  libraries/dompdf/lib/class.pdf.php
Zeile 1969
{code type=PHP }
@ini_set(‘memory_limit’, ’128M’);
{/code}

Das hilft bis eine gut Lösung gefunden ist

Robert Schöbel | Uncategorized | No comments Jump to the top of this page

DomPDF header / footer

April 9th, 2010

Bis jetzt habe ich immer FPDF verwendet, allerdings ist es in FPDF nur schwer möglich (bzw. ich habe keine gute Lösung gefunden) Bilder in einer Zelle unterzubringen.

Mit DOMPDF ist dies einfacher zu realisieren, da HTML interpretiert wird.

(INFO: ich nutze Codeigniter als PHP MVC Framework)

Nun zum Problem

  • in DOMPDF ist ein Header oder Footer nur mit Inline-Code realisierbar
  • Anforderung 1:   kein Inline-Code für den Header
  • Anforderung 2:  den Header mit einem Controller steuern.
  • Anforderung 3:  ein Text, ein Bild und eine Linie im Header

Die Seitennummerierung erfolgt im Moment mit Inline-PHP-Code

Dieser Code befindet sich ganz normal in einer HTML / PHP Seite

<html>...<head>....</head>

<body>

<script type="text/php">
if ( isset($pdf) ) {

$font = Font_Metrics::get_font("verdana");
// If verdana isn't available, we'll use sans-serif.
if (!isset($font)) { Font_Metrics::get_font("sans-serif"); }
$size = 6;
$color = array(0,0,0);
$text_height = Font_Metrics::get_font_height($font, $size);

$foot = $pdf->open_object();

$w = $pdf->get_width();
$h = $pdf->get_height();

// Draw a line along the bottom
$y = $h - 2 * $text_height - 24;
$pdf->line(45, $y, $w - 16, $y, $color, 1);

$y += $text_height;

$pdf->close_object();
$pdf->add_object($foot, "all");

$text = "Page {PAGE_NUM} of {PAGE_COUNT}";

// Center the text
$width = Font_Metrics::get_text_width("Page 1 of 2", $font, $size);
$pdf->page_text($w / 2 - $width / 2, $y, $text, $font, $size, $color);

}
</script>

....html tags und Codeigniter Variablen

</body>

</html>

Dompdf interpretiert erst alle HTML Elemente, normale  PHP Tags werden wie immer vorher interpretiert (<? echo “dies und das”; ?>)

Danach geht dompdf erneut durch den Code und bearbeitet die im mit  <script type=”text/php”> </script> gekennzeichneten Abschnitte.

Nun zur Header Lösung ohne Inline-PHP-Code (Workaround)

Damit das ganze funktioniert, muss ein wenig Vorarbeit geleistet werden.

Der DOMPDF Ordner befindet sich in system->application->libraries->dompdf

Es ist im nächsten Schritt zu ermitteln, welcher  PDF-Adapter verwendet wird, ich nutze cpdf (wird ein anderer genutzt, kann die Änderung analog vorgenommen werden)

Danach wird die Datei geöffnet: system->application->libraries->dompdf->include->cpdf_adapter.cls.php

In der Datei ist bereits eine Funktion “page_text” zu finden, mit ihr kann  Text auf jeder beliebigen Seite einfügt werden

/**
* Writes text at the specified x and y coordinates on every page
*
* The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced
* with their current values.
*
* See {@link Style::munge_colour()} for the format of the colour array.
*
* @param float $x
* @param float $y
* @param string $text the text to write
* @param string $font the font file to use
* @param float $size the font size, in points
* @param array $color
* @param float $adjust word spacing adjustment
* @param float $angle angle to write the text at, measured CW starting from the x-axis
*/

function page_text($x, $y, $text, $font, $size, $color = array(0,0,0),
$adjust = 0, $angle = 0) {
$_t = "text";
$this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "adjust", "angle");
}

Neben Text benötige ich noch eine Linie und ein Bild im Header.


Deswegen werden nun die folgenden Funktionen/Methoden angefügt

/**
* Processes a line on every page
*
*
*/

function page_line($x1, $y1, $x2, $y2, $color, $width, $style = array(),
$blend = "Normal", $opacity = 1.0) {
$_t = "line";
$this->_page_text[] = compact("_t", "x1", "y1", "x2", "y2", "color", "width", "style",
"blend", "opacity");
}
//........................................................................

/**
* Processes a image on every page
*
*/

function page_image($img_url, $img_type, $x, $y, $w, $h) {
$_t = "image";
$this->_page_text[] = compact("_t", "img_url", "img_type", "x", "y", "w", "h");
}

//........................................................................

Dann werden die Methode gesucht, in der die Daten verarbeitet werden (_add_page_text)

Die Methode muss  folgendermaßen angepasst werden

/**
* Add text to each page after rendering is complete
*/

protected function _add_page_text() {

if ( !count($this->_page_text) )
return;

$page_number = 1;
$eval = null;

foreach ($this->_pages as $pid) {
$this->reopen_object($pid);

foreach ($this->_page_text as $pt) {
extract($pt);

switch ($_t) {

case "text":
$text = str_replace(array("{PAGE_NUM}","{PAGE_COUNT}"),
array($page_number, $this->_page_count), $text);
$this->text($x, $y, $text, $font, $size, $color, $adjust, $angle);

break;

case "script":
if (!$eval) {
$eval = new PHP_Evaluator($this);
}
$eval->evaluate($code, array('PAGE_NUM' => $page_number, 'PAGE_COUNT' => $this->_page_count));
break;

//-----neu--------

case "line":

$this->line($x1, $y1, $x2, $y2, $color, $width, $style = array(),
$blend, $opacity );
break;
case "image":

$this->image($img_url, $img_type, $x, $y, $w, $h);
break;
}

}

$this->close_object();
$page_number++;
}
}

Das Ganze ist noch nciht 100 % perfekt, aber funktioniert erstmal (besser ist es, wenn Klassen abgeleitet werden)

Wie wird dies  jetzt in  Codeigniter genutzt?

Als Beispiel soll uns ein einfacher Controller dienen

class controllerxy{

.....

function export_lack_2_pdf(){
require_once(APPPATH . 'libraries/dompdf/dompdf_config.inc.php');

/* man hat irgendwo sein  HTML Template liegen

*das lässt man erstmal mit dem view-handler

*von codeigniter verarbeiten

*/


$html =  $this->load->view("content/mangel/templates/export_html.php", $this->data,true);

$my_font_family = "Arial";
$dompdf = new DOMPDF();
$dompdf->set_paper('A4');
$dompdf->load_html($html);

$dompdf->render();

//nun kommt der Header-Teil
$font = Font_Metrics::get_font($my_font_family);
$left = 45;
$text = $this->lang->line('ein_beispieltext_aus_der_lang_datei');

$size = 14;

$color = array(0,0,0);

//canvas holen (das liegt beim inline code bereits vor bzw. wurde übergeben)
$pdf = $dompdf->get_canvas();

//ein Text einfügen (das ist standard)

$pdf->page_text($left, 35, $text, $font, $size, $color);

//nun ein Bild

//FCPATH wird in Codeigniter bereitgestellt

$bild = FCPATH."/img/logo.png";

//Größe verändern
$info = getimagesize( $bild );
//
//es soll auf  Breite 100px skaliert werden
$w = 100;
$b = ceil($w * $info[1] / $info[0]);
$pdf->page_image($bild, "png", 450, 15,$w, $b);
//nun noch eine Linie
$pdf->page_line($left, 100, 530, 100, array(0,0,0), 1);

//jetzt der Export

$time = time();
// $dompdf->stream("mangel_".$time.".pdf",array("Attachment" => 0));
$dompdf->stream("mangel_".$time.".pdf");

}

.....

}

Ich hoffe ich es hilft jemandem, für Verbesserungen und Tipps bin ich offen

mfg Robert

Robert Schöbel | PHP | 1 comment Jump to the top of this page

Ignore files which are already versioned

April 9th, 2010

Es gibt dazu auch eine Anleitung von Tortoise

nur noch mal für mich

  1. Ordner suchen der ignoriert werden soll aber bereits im svn ist
  2. Shift Taste gedrückt halten und den Ordner auswählen
  3. Rechtsklick auf den Ordner –>  TortoiseSVN –> Delete (keep local)
  4. in den Parent-Ordner gehen und diesen Commiten
  5. Nun den Ordner auf Ignore setzen TortoiseSVN –> Add to ignore list
  6. den Parent-Ordner nocheinmal Commiten
  7. Sollte noch ein Fehler vorkommen kann auch ein clean up helfen

Robert Schöbel | SVN | No comments Jump to the top of this page

Mängelfeststellung und Restleistung

April 8th, 2010

Neues Feature in Speedupwork

Es ist jetzt möglich in der Baubericht/Bautagebuch Software Speedupwork Mängelfeststellungen und Restleistung zu verzeichnen und diese zu exportieren. Dies kann natürlich inklusive Bild erfolgen.

Robert Schöbel | Uncategorized | No comments Jump to the top of this page

SVN-Repository anlegen

March 5th, 2010

Auf meinem Debian Server liegt ein SVN-Repository.
Da ich nicht jeden Tag ein neues Repository anlege, folgt hier eine kleine Anleitung als Gedankenstütze.

Verzeichnis anlegen
{code type=text}
svnadmin create ––fs-type fsfs /var/svn-repos/my_project
{/code}

Rechte anlegen

{code type=text}
chown -R www-data:subversion /var/svn-repos/*
chmod -R 770 /var/svn-repos/*

{/code}

Passwort anlegen wenn der User noch nicht existiert

{code type=text}

htpasswd2 /etc/apache2/dav_svn.passwd robert

{/code}

Rechte für das Repository zuweisen

{code type=text}
nano /etc/apache2/dav_svn.authz

{/code}

Die Datei “/etc/apache2/dav_svn.authz” sollte folgendermaßen aussehen

{code type=text}
[/]
robert= rw
[other_repos:/]
robert= rw
[my_project:/]
robert= rw
{/code}

Das WebDav-Verzeichnis dem Apache bekanntmachen

{code type=text}
nano /etc/apache2/mods-available/dav_svn.conf

{/code}

Das ist der Inhalt der dav_svn.conf

{code type=text}

<Location /svn>

DAV svn
SVNParentPath /var/svn-repos/
AuthType Basic
AuthName “Subversion Repository”
AuthUserFile /etc/apache2/dav_svn.passwd
AuthzSVNAccessFile /etc/apache2/dav_svn.authz
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require user robert
</LimitExcept>

</Location>

<Location /svn/my_project>
Require user robert
</Location>

{/code}

Apache neustarten
{code type=text}

/etc/init.d/apache2 restart

{/code}

Robert Schöbel | SVN | No comments Jump to the top of this page

Date Time in PHP

March 4th, 2010

Date und Time spielen bei Nutzeroberflächen eine große Rolle und man stößt so ziemlich bei jeder Applikation auf die selben Probleme.
Problem:

GUI mit zwei Input Feldern, eins für das Datum und eins für die Zeit.

  1. Wie bekommt man Datum und Zeit aus einer Web-Oberfläche zu einem MySQl-Timestamp
  2. Wie bekommt man sie wieder aus der Datenbank in in die Inputfelder

Lösung:

Inputformat vom Datum ist 04.03.2010 also d.m.Y

Inputformat von der Zeit ist 13:38:02 also H:i:s

Als erstes Daten von der Web-Oberfläche empfangen und als ein String verpacken.

WebGUI –> PHP –> MySQL-DB

{code type=PHP}

…..

<input type=”text” id=”datum_start” name=”datum_start” value=”04.03.2010″ />

<input type=”text” id=”zeit_start” name=”zeit_start” value=”13:38:02″ />

….

{/code}

Backend

{code type=PHP }

$datum_zeit_start = $this->input->post(‘datum_start’).” “.$this->input->post(‘zeit_start’);

{/code}

$this-&gt;input-&gt;post('datum_start') 

steht in Codeigniter für

 $_POST['datum_start']

Dann kann man den String in einen Timestamp wandeln und diesen in das gewünschte Format überführen

{code type=PHP}

$timestamp_ready_for_db = date(“Y-m-d H:i:s”,strtotime($datum_zeit_start));

{/code}

Jetzt kann der Timestamp in die Datenbank geschrieben werden.

MySQL-DB –> PHP–>WEB-GUI
Im nächsten Schritt soll das Datum und die Zeit wieder aus der DB in die Inputfelder gelangen.
Dies geht etwas einfacher man liest die Datum-Zeit Spalte aus und wandelt sie folgendermaßen um.

{code type=PHP}

$datum = strftime(“%d.%m.%Y”,strtotime($timestamp_from_db));

{/code}

{code type=PHP}

$zeit = strftime(“%H:%M:%S”,strtotime($timestamp_from_db));

{/code}

strftime  gibt einen String zurück der den Formatierungs-Merkmalen entspricht.

strtotimeWandelt ein beliebiges in englischer Textform angegebenes Datum in einen UNIX-Zeitstempel (Timestamp) um (Quelle: php.net)

Ich hoffe jemanden hilft dieses kleine Beispiel und evtl. gibt es ja Verbesserungsvorschläge

Robert Schöbel | PHP | No comments Jump to the top of this page

JSF-selectOneMenu

January 22nd, 2010

Habe heute leider ein wenig Zeit mit der Suche nach einem Fehler verschwendet

{code type=HTML}

<h:selectOneMenu value=”#{lCB.lehrer.titel}” id=”titel”
required=”true”
requiredMessage=”#{msg.titel} #{msg.waehlen}”>

<f:selectItem value=”#{lCB.titelItems}” />

</h:selectOneMenu>

{/code}

Fehler:

Cannot coerce type java.util.List to
javax.faces.model.SelectItem

Lösung:

selectItem –> selectItems

Es hat einfach nur das “s” bei selectItem gefehlt.

Evtl. hilft es jemand Zeit zu sparen

Robert Schöbel | JAVA, Uncategorized | No comments Jump to the top of this page

Templating mit Facelets

January 18th, 2010

In JavaServer Faces gelangt man via “String”-Rückgabe von JSP-Seite zu JSP-Seite. Man lädt jede Seite also komplett neu.

Was macht man wenn jede Seite das gleiche Design haben soll?

Problem:  ich müsste jetzt auf jeder Page das Design mitschleifen, dies würde aber zu redundantem Code und  schlechter Wartbarkeit führen

  • in php habe ich das bisher mit Includes gelöst
  • ohne JSF mit JSP-only auch mit Includes

Lösung für JSF heißt Facelets mit Templating

so in etwa sah meine faces-config.xml aus (spielt eigentlich keine rolle)

fach_confi_faces

Als erstes musste in der faces-config.xml der Facelet-View-Handler aktiviert werden.

{code type=JAVA}

<application>

<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>

{/code}

nun muss noch die jsf-facelets.jar in den WebContent/WEB-INF/lib Folder.

Dannach muss die web.xml angepasst werden.

{code type=XML}

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 1 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>

{/code}

Wichtig ist auch der DEFAULT_SUFFIX, ich habe ihn auf .jsp gestellt.

Eer ist bei anderen tutorials auf .xhtml gestellt gewesen, ich wollte meine Dateien aber mit der Endung .jsp haben. Man könnte auch eine eigene Endung festlegen z. B. : “own”.

{code type=XML}

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
</context-param>

{/code}

Templating

Man erstellt als erstes sein Template, bei mir ist das template.jsp

obwohl die Datei Endung .jsp ist muss sie dem xhtml DOCTYPE genügen.

{code type=HTML}

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”

xmlns:ui=”http://java.sun.com/jsf/facelets”>

head>

<meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />

<title>Schöbel.net</title>

</head>

<link

href=”#{facesContext.externalContext.requestContextPath}/design/css/my_layout.css”

rel=”stylesheet” type=”text/css” />

<ul>

<ui:insert  name=”navigation_help”>

Default Menü

</ui:insert>

</ul>

<ui:insert name=”content”>

Default Body

</ui:insert>

</body>

</html>

{/code}

Wichtig sind die ui:insert Tags, sie schaffen Platzhalter die später Überschrieben werden können.

{code type=HTML}

<ui:insert  name=”navigation_help”>

Text der überschrieben wird

</ui:insert>

{/code}

Jetzt kann man das Template nutzen.

Bei mir wäre das meine Ausgangsseite admin.jsp

{code type=HTML}

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”

xmlns:ui=”http://java.sun.com/jsf/facelets”>

<head>

<meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />

</head>

<body>

<ui:composition template=”template.jsp”>

<ui:define name=”navigation_help”>

<li><strong>Hauptmenü</strong></li>

<li><em>bearbeiten </em></li>

<li><em>Ende</em></li>

</ui:define>

<ui:define name=”content”>

Das ist Inhalt der den Default Inhalt überschreibt

</ui:define>

</ui:composition>

</body>

</html>

{/code}

Als erstes verweist man auf das Template ui:composition.

Dannach kann man den Bereich definieren den man überschreiben möchte. Dazu nutzt man das Tag ui:define.

{code type=HTML}

<ui:composition template=”template.jsp”>

<ui:define name=”navigation_help”>

ich überschreibe navigation_help im template

</ui:define>

<ui:define name=”content”>

ich überschreibe content im template

</ui:define>

</ui:composition>

{/code}

Nun kann jede beliebige Seite aus der faces-config.xml angepasst werden

feritg

Robert Schöbel | JAVA | 2 comments Jump to the top of this page

mehrere faces-config.xml

January 8th, 2010

Heute stand ich vor dem Problem mehrere faces-configs in einen Java Server Faces Projekt zu integrieren

{code type=XML}

<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>

/WEB-INF/faces-config.xml,

/WEB-INF/faces-config-admin.xml

</param-value>
</context-param>

{/code}

wichtig ist die Zeile

{code type=XML}

<param-name>javax.faces.CONFIG_FILES</param-name>

{/code}

vorher hieß der Parameter CONFIG_FILE ohne S

Robert Schöbel | JAVA | No comments Jump to the top of this page