Results for category "Google"

7 Articles

Google Chrome

Gestern wurde Google Chrome als Beta veröffentlicht und so musste ich den kommenden Webbrowser von Google gleich mal antesten.
Die Installation lässt komischerweise keine Wahl, wohin man den Browser installieren möchte und auch der Import der Firefox-Daten funktioniert (noch) nicht.

Vom Browser selbst bin ich an sich recht begeistert. wap.ecw.de lässt sich mit Chrome um den Faktor 4 in Relation zum Firefox schneller laden.
Mein Firefox ist zwar auch mit vielen Plugin-Ins zugemüllt, aber ausschlaggebend ist meines Erachtens der dp.SyntaxHighlighter, der den Quellcode farbig hervorhebt.

Gut gefällt mir, dass standardmäßig die deutsche Rechtschreibprüfung aktiviert ist – muss man beim Firefox nachinstallieren und braucht ziemlich viel Ressourcen.

HTML-textarea-Elemente lassen sich übrigens in der Größe ändern, was ich auch ganz nett finde.

Sobald die ersten Erweiterungen (Mouse Gesture, Firebug, LiveHeader) für Chrome erscheinen sollten, werde ich eine Wechsel in Betracht ziehen.

Google Mobile Map API für PHP

Von http://www.witracks.com.br/gmaps.txt

<?php
$data =
"x00x0e". // Function Code?
"x00x00x00x00x00x00x00x00". //Session ID?
"x00x00". // Contry Code
"x00x00". // Client descriptor
"x00x00". // Version
"x1b". // Op Code?
"x00x00x00x00". // MNC
"x00x00x00x00". // MCC
"x00x00x00x03".
"x00x00".
"x00x00x00x00". //CID
"x00x00x00x00". //LAC
"x00x00x00x00". //MNC
"x00x00x00x00". //MCC
"xffxffxffxff". // ??
"x00x00x00x00"  // Rx Level?
;
if ($_REQUEST["myl"] != "") {
  $temp = split(":", $_REQUEST["myl"]);
  $mcc = substr("00000000".dechex($temp[0]),-8);
  $mnc = substr("00000000".dechex($temp[1]),-8);
  $lac = substr("00000000".dechex($temp[2]),-8);
  $cid = substr("00000000".dechex($temp[3]),-8);
} else {
  $mcc = substr("00000000".$_REQUEST["mcc"],-8);
  $mnc = substr("00000000".$_REQUEST["mnc"],-8);
  $lac = substr("00000000".$_REQUEST["lac"],-8);
  $cid = substr("00000000".$_REQUEST["cid"],-8);
}
$init_pos = strlen($data);
$data[$init_pos - 38]= pack("H*",substr($mnc,0,2));
$data[$init_pos - 37]= pack("H*",substr($mnc,2,2));
$data[$init_pos - 36]= pack("H*",substr($mnc,4,2));
$data[$init_pos - 35]= pack("H*",substr($mnc,6,2));
$data[$init_pos - 34]= pack("H*",substr($mcc,0,2));
$data[$init_pos - 33]= pack("H*",substr($mcc,2,2));
$data[$init_pos - 32]= pack("H*",substr($mcc,4,2));
$data[$init_pos - 31]= pack("H*",substr($mcc,6,2));
$data[$init_pos - 24]= pack("H*",substr($cid,0,2));
$data[$init_pos - 23]= pack("H*",substr($cid,2,2));
$data[$init_pos - 22]= pack("H*",substr($cid,4,2));
$data[$init_pos - 21]= pack("H*",substr($cid,6,2));
$data[$init_pos - 20]= pack("H*",substr($lac,0,2));
$data[$init_pos - 19]= pack("H*",substr($lac,2,2));
$data[$init_pos - 18]= pack("H*",substr($lac,4,2));
$data[$init_pos - 17]= pack("H*",substr($lac,6,2));
$data[$init_pos - 16]= pack("H*",substr($mnc,0,2));
$data[$init_pos - 15]= pack("H*",substr($mnc,2,2));
$data[$init_pos - 14]= pack("H*",substr($mnc,4,2));
$data[$init_pos - 13]= pack("H*",substr($mnc,6,2));
$data[$init_pos - 12]= pack("H*",substr($mcc,0,2));
$data[$init_pos - 11]= pack("H*",substr($mcc,2,2));
$data[$init_pos - 10]= pack("H*",substr($mcc,4,2));
$data[$init_pos - 9]= pack("H*",substr($mcc,6,2));

if ((hexdec($cid) > 0xffff) && ($mcc != "00000000") && ($mnc != "00000000")) {
  $data[$init_pos - 27] = chr(5);
} else {
  $data[$init_pos - 24]= chr(0);
  $data[$init_pos - 23]= chr(0);
}

$context = array (
        'http' => array (
            'method' => 'POST',
            'header'=> "Content-type: application/binaryrn"
                . "Content-Length: " . strlen($data) . "rn",
            'content' => $data
            )
        );

$xcontext = stream_context_create($context);
$str=file_get_contents("http://www.google.com/glm/mmap",FALSE,$xcontext);

if (strlen($str) > 10) {
  $lat_tmp = unpack("l",$str[10].$str[9].$str[8].$str[7]);
  $lat = $lat_tmp[1]/1000000;
  $lon_tmp = unpack("l",$str[14].$str[13].$str[12].$str[11]);
  $lon = $lon_tmp[1]/1000000;
  echo "Lat=$lat <br> Lon=$lon";
  } else {
  echo "Not found!";
  }

?>

API für Google Mobile Maps

Nach einigem Suchen bin ich endlich fündig geworden. Neil Young hat die Pakete mit Wireshark analysiert und heraus kam folgender C#-Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Diagnostics;

/*
 * Sample code to obtain geo codes from a cell info
 * "GSM/UMTS" setting revealed by smuraro, thanks!
 */

/* (c) "Neil Young" (neil.young@freenet.de)
 *
 * This script/program is provided "as is".
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * GNU General Public License, see <http://www.gnu.org/licenses/>.
 */

namespace GMM {
    class Program {
        static byte[] PostData(int MCC, int MNC, int LAC, int CID, bool shortCID) {
            /* The shortCID parameter follows heuristic experiences:
             * Sometimes UMTS CIDs are build up from the original GSM CID (lower 4 hex digits)
             * and the RNC-ID left shifted into the upper 4 digits.
             */
            byte[] pd = new byte[] {
                0x00, 0x0e,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00,
                0x00, 0x00,
                0x00, 0x00,

                0x1b,
                0x00, 0x00, 0x00, 0x00, // Offset 0x11
                0x00, 0x00, 0x00, 0x00, // Offset 0x15
                0x00, 0x00, 0x00, 0x00, // Offset 0x19
                0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, // Offset 0x1f
                0x00, 0x00, 0x00, 0x00, // Offset 0x23
                0x00, 0x00, 0x00, 0x00, // Offset 0x27
                0x00, 0x00, 0x00, 0x00, // Offset 0x2b
                0xff, 0xff, 0xff, 0xff,
                0x00, 0x00, 0x00, 0x00
            };

            bool isUMTSCell = ((Int64)CID > 65535);

            if (isUMTSCell)
                Console.WriteLine("UMTS CID. {0}", shortCID ? "Using short CID to resolve." : "");
            else
                Console.WriteLine("GSM CID given.");

            if (shortCID)
                CID &= 0xFFFF;      /* Attempt to resolve the cell using the GSM CID part */

            if ((Int64)CID > 65536) /* GSM: 4 hex digits, UTMS: 6 hex digits */
                pd[0x1c] = 5;
            else
                pd[0x1c] = 3;

            pd[0x11] = (byte)((MNC >> 24) & 0xFF);
            pd[0x12] = (byte)((MNC >> 16) & 0xFF);
            pd[0x13] = (byte)((MNC >> 8) & 0xFF);
            pd[0x14] = (byte)((MNC >> 0) & 0xFF);

            pd[0x15] = (byte)((MCC >> 24) & 0xFF);
            pd[0x16] = (byte)((MCC >> 16) & 0xFF);
            pd[0x17] = (byte)((MCC >> 8) & 0xFF);
            pd[0x18] = (byte)((MCC >> 0) & 0xFF);

            pd[0x27] = (byte)((MNC >> 24) & 0xFF);
            pd[0x28] = (byte)((MNC >> 16) & 0xFF);
            pd[0x29] = (byte)((MNC >> 8) & 0xFF);
            pd[0x2a] = (byte)((MNC >> 0) & 0xFF);

            pd[0x2b] = (byte)((MCC >> 24) & 0xFF);
            pd[0x2c] = (byte)((MCC >> 16) & 0xFF);
            pd[0x2d] = (byte)((MCC >> 8) & 0xFF);
            pd[0x2e] = (byte)((MCC >> 0) & 0xFF);

            pd[0x1f] = (byte)((CID >> 24) & 0xFF);
            pd[0x20] = (byte)((CID >> 16) & 0xFF);
            pd[0x21] = (byte)((CID >> 8) & 0xFF);
            pd[0x22] = (byte)((CID >> 0) & 0xFF);

            pd[0x23] = (byte)((LAC >> 24) & 0xFF);
            pd[0x24] = (byte)((LAC >> 16) & 0xFF);
            pd[0x25] = (byte)((LAC >> 8) & 0xFF);
            pd[0x26] = (byte)((LAC >> 0) & 0xFF);

            return pd;
        }

        static void Main(string[] args) {

            if (args.Length < 4) {
                Console.WriteLine("Usage: gmm MCC MNC LAC CID ["shortcid"]");
                return;
            }
            string shortCID = "";   /* Default, no change at all */
            if (args.Length == 5)
                 shortCID = args[4].ToLower();

            try {
                String url = "http://www.google.com/glm/mmap";
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(url));
                req.Method = "POST";

                int MCC = Convert.ToInt32(args[0]);
                int MNC = Convert.ToInt32(args[1]);
                int LAC = Convert.ToInt32(args[2]);
                int CID = Convert.ToInt32(args[3]);
                byte[] pd = PostData(MCC, MNC, LAC, CID, shortCID == "shortcid");

                req.ContentLength = pd.Length;
                req.ContentType = "application/binary";
                Stream outputStream = req.GetRequestStream();
                outputStream.Write(pd, 0, pd.Length);
                outputStream.Close();

                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                byte[] ps = new byte[res.ContentLength];
                int totalBytesRead = 0;
                while (totalBytesRead < ps.Length) {
                    totalBytesRead += res.GetResponseStream().Read(ps, totalBytesRead, ps.Length - totalBytesRead);
                }

                if (res.StatusCode == HttpStatusCode.OK) {
                    short opcode1 = (short)(ps[0] << 8 | ps[1]);
                    byte opcode2 = ps[2];
                    System.Diagnostics.Debug.Assert(opcode1 == 0x0e);
                    System.Diagnostics.Debug.Assert(opcode2 == 0x1b);
                    int ret_code = (int)((ps[3] << 24) | (ps[4] << 16) | (ps[5] << 8) | (ps[6]));

                    if (ret_code == 0) {
                        double lat = ((double)((ps[7] << 24) | (ps[8] << 16) | (ps[9] << 8) | (ps[10]))) / 1000000;
                        double lon = ((double)((ps[11] << 24) | (ps[12] << 16) | (ps[13] << 8) | (ps[14]))) / 1000000;
                        Console.WriteLine("Latitude: {0}, Longitude: {1}", lat, lon);

                        Process p = new Process();
                        p.StartInfo.FileName = "iexplore";

                        Console.WriteLine("nClose map window to exitn");

                        p.StartInfo.Arguments = String.Format(
                            "http://maps.google.de/maps?f=q&hl=de&q={0},{1}&ie=UTF8&z=15",
                            lat.ToString().Replace(',','.'), lon.ToString().Replace(',','.'));
                        p.Start();
                        p.WaitForExit();
                    }
                    else
                        Console.WriteLine("Error {0}", ret_code);
                }
                else
                    Console.WriteLine("HTTP Status {0} {1}", res.StatusCode, res.StatusDescription);
            }
            catch (Exception) {
                throw;
            }
        }
    }
}

Sehr gute Arbeit!
Die Beschreibung des Hexdumps gibt es unter http://maps.alphadex.de/datafiles/fct0e1b117823ccc1a.txt, der Blog von Neil ist unter http://foreverneilyoung.blogspot.com/ zu finden.

Weitere Infos: Anleitung zum Schreiben einer eigenen Anwendung mit GMM-API in Java
Google Maps Mobile API in Python.

Google zensiert gnadenlos

In meinem letzten Post berichtete ich über Google Maps Mobile und heute musste ich feststellen, dass in den Google Groups alle Beiträge, die irgendetwas mit der Google Mobile Maps API zu tun haben, gnadenlos gelöscht wurden.
Google hat offensichtlich keine Lust, die API der Öffentlichkeit zur Verfügung zu stellen. Ich finde diese Art der Zensur mehr als dreist.

Analyse der Google Mobile Maps API

Den heutigen Abend war ich damit beschäftigt, mich um das Thema GPS-Lokalisierung zu kümmern. Dabei kamen dann einige interessante Dinge zu Tage. Zum einen wusste ich gar nicht, dass o2 einen Handy-Lokalisierungsdienst für lau anbietet. Nachdem man sich in das o2-Portal eingeloggt hat, kann man dort sein Handy lokalisieren. Nach einigen Sekunden erscheint in einer -billig gemachten- Karte der ungefähre Bestimmungsort des Handys. Mein Handy wurde ca. 1.6 Kilometer zu weit nördlich angezeigt, aber das bleibt nun mal nicht aus.
Meine andere Erkenntnis war, das man mit Google Maps Mobile http://www.google.com/gmm/tour.html?hl=de sich ebenfalls den Standort des Handys anzeigen lassen kann. Die J2ME-Applikation sucht sich die Cell ID des Betreibers heraus, in dem das Handy eingeloggt ist. Google hat wohl mit den großen Handynetz-Betreibern Verträge geschlossen, so dass sie auf die Zell-Datenbanken zugreifen können.

Leider konnte ich die J2ME-Anwendung auf meinem P910i nicht installieren. Ich schaute deshalb nach, ob man eventuell die Demo benutzen kann, um die API mit anderen Tools zu benutzen.
Nachdem ich die passende JAR-Datei heruntergeladen habe, musste ich leider feststellen, dass über die Sourcen ein Obfuscator gejagt wurde – ok ich hätte das wohl auch so gemacht 😉

Ich baute mir ein kurzes Shellscript:

#!/bin/bash
find -name "*class" | sed 's/.class//g' | sed 's/.///g' >> files.txt

for clazz in `cat files.txt`;
do
    echo "FILE $clazz" >> code.txt
    javap -c $clazz >> code.txt
done

Und hatte somit von den allen Klassen den dekompilierten Byte-Code. Viel anfangen konnte ich damit leider nicht, ich stellte nämlich fest, dass die komplette Verbindung zwischen J2ME-Client und Google Maps Mobile im Binärformat abgewickelt wird.
Frontcontroller der Server-API ist http://www.google.com/glm/mmap – und das war es auch schon. Also leider nix mit REST o.ä.
Der Client stellt eine Anfrage über POST als Client “MobileRunner” im Binärformat, der Server sendet die Antwort ebenfalls als Binary zurück.

Tja, leider blöd gelaufen. Ich hätte gerne ein paar Anwendungen geschrieben, die auf die Google Mobile Maps-API setzen würden.