Archiv der Kategorie: PHP

Komplette IDE mit PHP- und Javascript-Debugging unter Windows unter Verwendung von Wampserver [v3.0.0] und „Eclipse for PHP Developers“ (Eclipse PDT) MARS.2 [v4.5.2]

Problem

Für das Debugging von PHP Webanwendungen wird eine PHP Debuggingumgebung benötigt.

Ansatz

Die kostenlose Anwendung WAMPSERVER (hier v.3.0.0) wird mit „Eclipse for PHP Developers“ (MARS.2) konfiguriert, um das Debugging zu ermöglichen.

Vorgehensweise

  • Download von Wampserver unter http://www.wampserver.de
  • Installation als Administrator (rechte Maustaste „als Administrator ausführen“)
    • z.B. in c:\dev\wamp
  • Download von „Eclipse for PHP Developers“ unter http://www.eclipse.org
  • Entpacken von „Eclipse for PHP Developers“ in ein gewünschtes Verzeichnis

Lösung

Nachdem der Wampserver gestartet wurde und unter der URL http://localhost erreichbar ist, kann bereits mit der Konfiguration von Eclipse begonnen werden.

  1. Eclipse starten
  2. Workspace direkt im WWW root auswählen (bspw. bei Installation in c:\dev\wamp)
    workspace
  3. Mit OK bestätigen
  4. Im Menü „Window -> Preferences“ wählen
    menu_window_preferences
  5. PHP Executable hinzufügen
    PHP_Executables
  6. PHP Executable angebenTab_PHP_Executable
  7. Unten auf den Button „Next->“ klicken (nicht im Screenshot da Edit-Dialog)
  8. Debugger angeben -> XDebug auswählen!Tab_Debugger
  9. Mit okay bestätigen
  10. Einstellungen unter Menu->Preferences->Debug überprüfen (ist der angelegte Debugger aktiviert?).einstellungen_debug
  11. Web Browser angeben (ich empfehle Google Chrome)eclipse_preferences_webbrowser
  12. Neues PHP Projekt anlegen
    neues_php_projekt
  13. Folgende Einstellungen tätigen neues_php_projekt_auswahl
  14. Rechtklick auf das neu angelegte Projekt -> New -> PHP Fileneues_php_projekt_datei_hinzufuegen
  15. Die Datei beispielsweise index.php benennen new_phpfile_index_benennen
  16. Test-Sourcecode in index.php einfügen
    <?php
    	$i=0;
    	$i++;
    	$i=$i+1;
    	print $i;
    ?>
    
  17. Breakpoint setzen (Doppelklick links neben die Zeile)
    debug_configuration_index_Debugger2
  18. Debug Configuration für die Website anlegen (rechts neben die Debug Wanze klicken -> Debug Configurations)
    debugger_wanze
  19. Debug Configurations -> PHP Web Application -> index -> Server
    debug_configuration_index_serverDie Startdatei /Bier.de/index.php entspricht auch dem Aufruf über http://localhost/Bier.de/index.php, da wir den Workspace im c:\dev\wamp\www-rootverzeichnis angelegt haben.
  20. Debug Configurations -> PHP Web Application -> index -> Debugger
    debug_configuration_index_Debugger
    Wenn „Break at First Line“ ausgewählt ist, hält der Debugger automatisch bei der ersten Zeile an. Dies ist nicht immer gewünscht!
  21. Debug Button klicken
  22. Bestätigen dass auf die PHP Debug Perspektive gewechselt wird
  23. Für das Javascript-Debugging Empfehle ich dringend den ausgereiften Chrome Javascript Debugger zu verwenden. Dieser lässt sich in Chrome folgendermaßen starten:
    chrome-debugger1
  24. Hier kann man Breakpoints setzen und den Objektbaum jederzeit einsehen:
    chrome-debugger2

 

 

 

 

Android&PHP Backend: Netzwerkkommunikation, Authentifizierung und Login

Aufgabenstellung

Es wird eine Möglichkeit gesucht eine Android App mit einen PHP Backend kommunizieren zu lassen

Intention

PHP mit MySQL Server erhält man oft schon mit billigem Webspace. Ein weiterer Vorteil eines fertigen Webpacks/Webspace ist, dass es nicht notwendig wird sich um eine Backupstrategie zu kümmern. In den meisten Fällen (SLAs und AGBs des Providers studieren) liegt dieses Problem in den Händen des Providers. Er kümmert sich auch um die Sicherheit des Servers. Bei Hackerattacken ist man nicht in der Verantwortung den Server zu härten und zu schützen. Daher kann der Provider auch keine Schadensersatzansprüche gegen den Kunden geltend machen, wenn ein Server gekapert wird und z.B. mit der Installation eines Botnetzes die Leistungsfähigkeit des Rechenzentrums beeinträchtigt ist.

Ansatz

  • Implementierung eines möglichst einfachen Authentifierungsmechanismus in PHP mit MySQL-Anbindung
  • Wegkapseln der Serviceaufrufe
  • Asynchrone Verarbeitung der JSON Aufrufe per Java Thread
    • Reaktion in der MainActivity beim Erhalten des Service-Ergebnisses für UI Manipulationen

Der häufigste Ansatz, den man in Tutorials findet, ist die Kommunikation über JSON, einem kompakten Datenformat in für Mensch und Maschine einfach lesbarer Textform zum Zweck des Datenaustauschs zwischen Anwendungen.

Lösung

BjoernServiceCaller.java – Klasse für weggekapselte Service aufrufe mit CallBack-Funktionalität über onLoginResult

package com.caprisoft.contactupload.services;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import com.caprisoft.contactupload.MainActivity;

import android.content.Context;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;


public class BjoernsServiceCaller 
{
	
	final String authenticationURL = "authenticationservice.php";
	private static BjoernsServiceCaller instance = null;
	private BjoernsServiceCaller() 	{}
	

    /**
     * Statische Methode, liefert die einzige Instanz dieser
     * Klasse zurück
     */
    public static BjoernsServiceCaller getInstance() 
    {
        if (instance == null) 
        {
            instance = new BjoernsServiceCaller();
        }
        return instance;
    }
	
	
	public void loginUser(final MainActivity ctx, 
                                    final String email, final String password) 
	{
        Thread t = new Thread()
        {
	        public void run() 
	        {
                        //For Preparing Message Pool for the child Thread
		        Looper.prepare(); 
				
		        HttpClient client = new DefaultHttpClient();
                         //Timeout Limit
		        HttpConnectionParams
                               .setConnectionTimeout(client.getParams(), 10000);
		        HttpResponse response;
		        JSONObject json = new JSONObject();
		        try
		        {
		            HttpPost post = new HttpPost(authenticationURL);
		            json.put("email", email);
		            json.put("password", password);
		            StringEntity se = new StringEntity( json.toString());  
		            se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
                                          application/json"));
		            post.setEntity(se);
		            response = client.execute(post);
		            /*Checking response */
		            if(response!=null)
		            {
		                BufferedReader reader = new BufferedReader
                                (
                                    new InputStreamReader
                                    (
                                       response.getEntity().getContent(), "UTF-8"
                                    )
                                );
		                String derText = reader.readLine();
                                // CallBack aufruf in MainActivity
		                ctx.onLoginResult(derText);
		            }
		
		        }
		        catch(Exception e)
		        {
		            e.printStackTrace();
		        }
		        Looper.loop(); //Loop in the message queue
	        }
        };
        t.start();          
    }
}

authenticationservice.php – Das PHP Backend, was die Datenbankabfragen macht und auf jedem Billigwebspace läuft

<?php  
    include("configuration/database.php");
	$json = file_get_contents('php://input');
	$obj = json_decode($json);
	$result2=mysql_query("SELECT id, activationcode FROM users ".
                                      "WHERE email='".$obj->{'email'}."' AND ".
                                      "password='".$obj->{'password'}."'") 
                                       or die(mysql_error());
	
	$user="nouser";
	while ($row = mysql_fetch_array($result2, MYSQL_NUM)) {
	   $user=$row[0];
	   $activationcode=$row[1];
	}	
    
    $posts = array(1);
    
    if($user!="nouser")
    {
    	if($activationcode=="activated")
    	{
    		session_start();
    		session_register("userid");
    		$_SESSION["userid"] =$user;
    		header('Content-type: application/json');
    		echo "success";
    	}
    	else 
    	{
    	   $registrationcode=substr(md5($obj->{'email'}." ".$obj->{'password'}),6);
    	   mysql_query("UPDATE users SET activationcode='".$registrationcode.
           "' WHERE email='".$obj->{'email'}."'") or die(mysql_error());
    	   mail($obj->{'email'},"Registrationcode for contactupload.com",
            "Hello!<br><br>\n You or someone else has registered this email ".
            "address via mobile phone.<br><br>\nThe generated registrationcode is ".
            $registrationcode.".<br><br>\nPlease type this registrationcode in ".
            "the register section of the contact sync app.<br><br> .
            "\nWith best regards,<br>\ncontactupload.com");
    		echo "not activated";
    	}
    }
    else 
    {
        echo "not registered";
    } 
    mysql_close($con);
?>

MainActivity.java – Die Klasse präsentiert den Code der Benutzeroberfläche der Activity (VIEW)

package com.caprisoft.contactupload;

import com.caprisoft.contactupload.services.BjoernsServiceCaller;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
	
	private EditText email = null;
	private EditText passwort = null;
	
	/** Called when the user selects the Send button */
	public void onClickLoginButton(View view) {
	    // Do something in response to button
		Log.d(this.getClass().toString(), "Login Button gedrückt!");
		BjoernsServiceCaller.
                getInstance().
                loginUser
                (
                    this, 
                    email.getText().toString(), 
                    passwort.getText().toString()
                );
	}
	
	/** Called when the user selects the Send button */
	public void onClickRegisterButton(View view) {
	    // Do something in response to button
		Log.d(this.getClass().toString(), "Register Button gedrückt!");
	}	
	
	public void onLoginResult(String text)
	{
		Toast.makeText(this, "HALLO: "+text, Toast.LENGTH_LONG).show();
	}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        email = (EditText) findViewById(R.id.textUsername);
        passwort = (EditText) findViewById(R.id.textPassword);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    
}

Activity_main.xml – Das eigentliche Frontend

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/labelUsername"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/labelUsername"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
  <EditText android:id="@+id/textUsername"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:inputType="textNoSuggestions"
        android:hint="@string/hintUsername" />
  
   <TextView
        android:id="@+id/labelPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/labelPassword"
        android:textAppearance="?android:attr/textAppearanceLarge" />
      
   <EditText android:id="@+id/textPassword"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:inputType="textPassword"
        android:hint="@string/hintPassword" />

   <Button
       android:id="@+id/buttonLogin"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="onClickLoginButton"
       android:text="@string/buttonLogin" />

   <Button
       android:id="@+id/buttonRegister"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="onClickRegisterButton"
       android:text="@string/buttonRegister" />
  
</LinearLayout>

AndroidManifest.xml – Permission für den Zugriff auf das Internet einrichten

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.caprisoft.contactupload"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
     <uses-permission android:name="android.permission.INTERNET" /> 
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>