Posts Tagged ‘JSON’

Samstag, 11. Februar 2023

PHP Race Condition beim Schreiben einer Datei

Mit monit überwache ich die Grösse der Datei /var/log/php.log auf meinen Web-Servern und alarmiere mich, wenn die Datei die Grösse von 1 MB überschreitet. Das geht natürlich nur, wenn man mit logrotate sicherstellt, dass die Datei täglich rotiert wird. Und wenn man so (defensiv) in PHP programmiert, dass das Log nicht infos, notices, warnings und errors vollgepflastert wird. Um es noch schwieriger zu machen: Ich habe in php.ini error_reporting = E_ALL aktiviert, denn das motiviert Web-Entwickler (mich), ihren Code sauber zu halten.

Vor einigen Tagen machte ich mich daran, ein immer wiederkehrendes Problem zu lösen, welches das Log füllte: Ich greife die Werte meiner ZigBee Temperatur-Sensoren ab und speichere sie auf einem Server in eine Datenbank. Gleichzeitig cache ich den aktuellsten Wert eines Sensors als JSON auch unter dem Web-Root eines Virtualhosts, damit ich den aktuellen Wert rasch und umkompliziert per HTTP abfragen kann.

Immer wieder kam dabei vor, dass beim Dekodieren solcher JSON-Dateien ein Fehler auftrat. Schlussendlich programmierte ich eine Routine, die solche JSONs mit falscher Syntax entdeckte und kurzerhand löschte. Dementsprechend führten Anfragen für die Cache-Dateien bestimmter Sensoren anschliessend zu dutzenden Einträgen in php.log, weil die Cache-Datei nicht mehr gefunden werden konnte:

[08-Feb-2023 19:06:34 Europe/Zurich] E - json_decode() returned null for path "/var/www/app/cache/BathroomWindow.json" but payload is 128 bytes. JSON error: "Syntax error". Unlinking file assuming it is malformed. in /var/www/app/class.php:258 for URI  (Referer: unknown) from IP 10.1.2.3 with User Agent "Mozilla/4.0 (compatible; cron/SERVER/USER/cron.sh)"
...
[08-Feb-2023 19:07:19 Europe/Zurich] E - Path "/var/www/app/cache/BathroomWindow.json" not found in /var/www/app/class.php:247 for URI  (Referer: unknown) from IP 10.1.2.3 with User Agent "Mozilla/4.0 (compatible; cron/SERVER/USER/cron.sh)"

Erst wenn der Sensor wieder ein Lebenszeichen sendete, konnte das Cache-File neu erstellt werden, und die Fehlermeldungen hörten auf.

Doch wieso war die JSON-Syntax zerschossen? Um dem auf den Grund zu gehen, baute ich in die Subroutine, welche die Syntaxprüfung durchführt, noch eine zusätzliche Zeile hinzu, welches den Inhalt der kaputten JSON-Datei in das Log schrieb. Hier ein Beispielresultat:

[09-Feb-2023 20:06:29 Europe/Zurich] E - JSON payload: "{"utime":1675969548,"sid":"158d000XXXXXXX","deviceName":"Office Mario Door","open":true,"deviceType":"magnet","battery":100}":100}" in /var/www/app/class.php:259 for URI  (Referer: unknown) from IP 10.1.2.3 with User Agent "Mozilla/4.0 (compatible; cron/SERVER/USER/cron.sh)"

Das letzte ":100} sollte wirklich nicht dort stehen und machte keinen Sinn. Es sah so aus, als ob die Datei zwei Mal geschrieben wurde: Zuerst mit einem längeren String, und gleich darauf mit einem kürzeren String. In der Tat ist es so, dass die ZigBee-Sensore manchmal innert Sekunden zwei oder mehrere Male Werte absenden. Könnte ich also einer Race Condition beim Schreiben von Dateie aufgesessen sein?

Wie man das löst? Wenn Prozess A die Cache-Datei schreibt, muss sie für andere Prozesse gesperrt werden. Tatsächlich kennt PHP das Flag LOCK_EX für file_put_contents(), und seit ich dieses mitgebe, hat sich das Problem (zumindest in den letzten 48 Stunden) nicht mehr wiederholt:

...
$res = file_put_contents($filename, $jsonOut, LOCK_EX);
...

Tags: , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 1. Dezember 2020

Mehrere Unix Timestamps auf der macOS Kommandozeile in Daten umwandeln

Voraussetzung: MacPorts und das Utility gdate (unter Linux: date) (Teil des Pakets coreutils) sind installiert.

$ python -mjson.tool < netatmo.json | grep utc | cut -d ":" -f 2 | awk '{print $1}' | xargs -I '{}' gdate -d "@{}"
Mon Nov 30 22:28:06 CET 2020
Mon Nov 30 22:27:57 CET 2020
Mon Nov 30 22:28:03 CET 2020
Mon Nov 30 22:27:38 CET 2020
Mon Nov 30 22:28:03 CET 2020
Mon Nov 30 22:28:03 CET 2020
Mon Nov 30 22:28:03 CET 2020
Mon Nov 30 17:07:34 CET 2020
Mon Nov 30 17:07:21 CET 2020
Mon Nov 30 17:07:21 CET 2020
Mon Nov 30 20:03:52 CET 2020
Mon Nov 30 20:03:52 CET 2020
Mon Nov 30 20:03:52 CET 2020
Mon Nov 30 20:03:52 CET 2020
Mon Nov 30 20:03:46 CET 2020
Mon Nov 30 22:07:42 CET 2020
Mon Nov 30 22:07:00 CET 2020
Mon Nov 30 22:07:07 CET 2020

Im vorliegenden Fall nahm mich Wunder, wann meine Netatmo-Sensoren das letzte Mal einen Wert an den Server übertragen hatten.

Mindestens zwei Stationen mit einer handvoll Sensoren haben den Wert seit gestern nicht mehr aktualisiert. Ich vermute auf Grund dieses Absturzes.

Hierzu lud ich über die Netatmo API das JSON mit den Daten aller meiner Stationen herunter, gab das JSON schön formatiert aus (ein Key-Value Pair pro Zeile), selektierte die Zeilen mit dem Attribut time_utc, isolierte deren Wert — die Unix Timestamp (ein Integer), entfernte die Leerzeichen vor und nach dem Wert und übergab die Liste der Werte mittels xargs dem Tool gdate zur Umwandlung in ein menschenlesbares Datum.

Tags: , , , , , , , , , , , , , ,
Labels: Apple, IT, Linux

Keine Kommentare | neuen Kommentar verfassen

Samstag, 14. Oktober 2017

upc cablecoms Verfügbarkeitsabfrage ist äusserst geschwätzig

upc cablecom bietet auf ihrer Web-Site die Möglichkeit, eine Wohnadresse auf die Verfügbarkeit von upc-Produkten zu überprüfen:

Verfügbarkeit prüfen

Füllt man die erforderlichen Angaben in das Formular ein, erhält man eine rein binäre Antwort für jede der drei Produktkategorien Internet, TV und Festnetz:

Im Hintergrund setzt dafür JavaScript eine Abfrage auf eine upc API ab. Die URL lautet für das vorliegende Beispiel:

https://www.upc.ch/aff-upc-cablecom-ch/aav/availability.json?streetName=Schl%C3%B6sslistrasse&streetNumber=39&postalCode=3008&_charset_=UTF-8&lang=de

Als Antwort erhält man eine Datei namens availability.json zurück. Nachfolgend das Beispiel für meine Wohnadresse:

{
    "addressResultState": "uniqueAddress",
    "addresses": [
        {
            "buildingNumber": 39,
            "buildingNumberAnnex": null,
            "buildingStatusId": 3,
            "buildingStatusName": "completed",
            "communeName": "Bern",
            "coordinateX": "599190",
            "coordinateY": "199475",
            "countryCodeA2": "CH",
            "idBuilding": 131767,
            "locationName1": "Bern",
            "locationName2": "Bern",
            "networkOperatorId": 0,
            "postCode": "3008",
            "postCodeAnnex": "00",
            "postOfficeName": "Bern",
            "stateName": "Bern/Berne",
            "stateShort": "BE",
            "streetName1": "Schl\u00f6sslistrasse"
        }
    ],
    "availability": {
        "accessProvider": null,
        "accessTechnology": null,
        "cablecomRegion": "Nord-West",
        "catv": {
            "available": true,
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "not available"
                ]
            },
            "partnerNetFlag": false
        },
        "dp": {
            "available": true,
            "availableFrom": {
                "day": 5,
                "fractionalSecond": 0.0,
                "hour": 0,
                "minute": 0,
                "month": 9,
                "second": 0,
                "timezone": 120,
                "year": 2000
            },
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "RVO_VSB01",
                    "RVO_VSB02",
                    "RVO_VSB03",
                    "RVO_VSB04",
                    "RVO_VSB05",
                    "RVO_FRC1",
                    "RVO_GBL1",
                    "RVO_FCG1",
                    "RVO_FRC2",
                    "RVO_GBL2",
                    "RVO_FCG2",
                    "RVO_FCE1",
                    "RVO_FCE2",
                    "RVO_FPW1",
                    "RVO_FPW2",
                    "RVO_FPS1",
                    "RVO_FPS2",
                    "RVO_FPP1",
                    "RVO_FPP2",
                    "RVO_BP1",
                    "RVO_BDS13",
                    "RVO_BDS14",
                    "RVO_BDS08",
                    "RVO_BDS11",
                    "RVO_BDS09",
                    "RVO_BDS12"
                ]
            },
            "partnerNetFlag": false
        },
        "dtv": {
            "available": true,
            "availableFrom": {
                "day": 1,
                "fractionalSecond": 0.0,
                "hour": 0,
                "minute": 0,
                "month": 1,
                "second": 0,
                "timezone": 60,
                "year": 1999
            },
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "",
                    "NR_SVD01",
                    "RDC_SFRSD",
                    "RDC_SFRS_M",
                    "RDI_CH01",
                    "RDI_CH04",
                    "RDI_CH05",
                    "RDI_CH06",
                    "RDI_CH07",
                    "RDI_CH08",
                    "RDI_CH09",
                    "RDI_CH09",
                    "RDI_CH10",
                    "RDI_CH11",
                    "RDI_CH17",
                    "RDI_CH17H",
                    "RDI_CH18",
                    "RDI_CH18H",
                    "RDI_CH19",
                    "RDI_CH19H",
                    "RDI_CH20",
                    "RDI_CH20H",
                    "RDI_CH21",
                    "RDI_CH21",
                    "RDI_CH21_M",
                    "RDI_CH21_M",
                    "RDI_CH22",
                    "RDI_CH22_M",
                    "RDI_CH24",
                    "RDI_CH24_M",
                    "RDI_CH25",
                    "RDI_CH25_M",
                    "RDI_CH26",
                    "RDI_CH26_M",
                    "RDI_CH27",
                    "RDI_CH27_M",
                    "RDI_CH28",
                    "RDI_CH28_M",
                    "RDI_CH30",
                    "RDI_CH31",
                    "RDI_CH32",
                    "RDI_CH33",
                    "RDI_CH40",
                    "RDI_CH40_M",
                    "RDI_CH41",
                    "RDI_CH41",
                    "RDI_CH42",
                    "RDI_CH44",
                    "RDI_CH47",
                    "RDI_CH47",
                    "RDI_CH48",
                    "RDI_CH49",
                    "RDI_CH50",
                    "RDI_CH51",
                    "RDI_CH52",
                    "RDI_CH53",
                    "RDI_CH54",
                    "RDI_CH55",
                    "RDI_CH56",
                    "RDI_CH57",
                    "RDI_CH59",
                    "RDI_CH60",
                    "RDI_CH61",
                    "RDI_CH62",
                    "RDI_CH65",
                    "RDI_CH66",
                    "RDI_CH67",
                    "RDI_CH68",
                    "RDI_CH72",
                    "RDI_CH73",
                    "RDI_CH74",
                    "RDI_CH81",
                    "RDI_CH93",
                    "RDI_CH97_M",
                    "RDI_D4A_97",
                    "RDI_DUMW",
                    "RDI_DWISR1",
                    "RDI_DWISS1",
                    "RDI_DWR1",
                    "RDI_DWS1",
                    "RDI_HCOD",
                    "RDI_HRZ06",
                    "RDI_HRZ11",
                    "RDI_HRZ17",
                    "RDI_HRZ17",
                    "RDI_CH81",
                    "RDI_HRZ17H",
                    "RDI_HRZ81",
                    "RDI_HRZ18",
                    "RDI_HRZ18H",
                    "RDI_HRZ19",
                    "RDI_HRZ19H",
                    "RDI_HRZ20",
                    "RDI_HRZ20H",
                    "RDI_HRZ21",
                    "RDI_HRZ21",
                    "RDI_HRZ22",
                    "RDI_HRZ24",
                    "RDI_HRZ25",
                    "RDI_HRZ26",
                    "RDI_HRZ27",
                    "RDI_HRZ28",
                    "RDI_HRZ40",
                    "RDI_HRZ52",
                    "RDI_HRZ53",
                    "RDI_HRZ83",
                    "RDI_HRZCL",
                    "RDI_HRZCO",
                    "RDI_HRZDS",
                    "RDI_HRZ_97",
                    "RDI_PREM1",
                    "RDI_PREM2",
                    "RDI_PREM_M",
                    "RDI_PRM",
                    "RDI_PRMM",
                    "RDI_SPTV",
                    "RDI_SPTV_M",
                    "RDI_SVD_51",
                    "RDI_SVD_51",
                    "RDI_SVD_51",
                    "RDI_SVD_52",
                    "RDI_SVD_52",
                    "RDI_SVD_52",
                    "RDI_SVD_59",
                    "RDI_SVD_60",
                    "RHZ_CLAS7",
                    "RHZ_CLAS8",
                    "RHZ_PREM1",
                    "RHZ_PREM2",
                    "RHZ_PRM",
                    "RHZ_SFRSH",
                    "RHZ_SPTV",
                    "RDI_CTDV",
                    "RDI_DUMS",
                    "RDI_DUMM"
                ]
            },
            "partnerNetFlag": false
        },
        "dtvActicationCode": "203",
        "dtvDistributionModel": "Vertriebsmodell Cablecom",
        "dtvSetupId": "01810000",
        "ftthBuildingStatus": null,
        "ftthSla": null,
        "hs": {
            "available": true,
            "availableFrom": {
                "day": 5,
                "fractionalSecond": 0.0,
                "hour": 0,
                "minute": 0,
                "month": 9,
                "second": 0,
                "timezone": 120,
                "year": 2000
            },
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "DHS_BSO",
                    "RHS_BDS06",
                    "RHS_BDS07",
                    "RHS_BDS08",
                    "RHS_BDS09",
                    "RHS_BDS10",
                    "RHS_BDS11",
                    "RHS_BDS12",
                    "RHS_BDS13",
                    "RHS_BDS14",
                    "RHS_BDS15",
                    "RHS_BDS16",
                    "RHS_BDS17",
                    "RHS_BDS18",
                    "RHS_BDS20",
                    "RHS_BDS21",
                    "RHS_HC256",
                    "RHS_HS02",
                    "RHS_HS05",
                    "RHS_HS06",
                    "RHS_HS08",
                    "RHS_HS09",
                    "RHS_HS11",
                    "RHS_HS12",
                    "RHS_HS13",
                    "RHS_HS14",
                    "RHS_HS15",
                    "RHS_HS16",
                    "RHS_HS17",
                    "RHS_HSED13",
                    "RHS_HSED21",
                    "RHS_HSED30",
                    "RHS_HSED32",
                    "RHS_NDH25",
                    "RHS_HSED10",
                    "RHS_HSED11",
                    "RHS_HSED12",
                    "RHS_HSED14",
                    "RHS_HSED15",
                    "RHS_HSED16",
                    "RHS_HSED17",
                    "RHS_HSED18",
                    "RHS_HSED19",
                    "RHS_HSED20",
                    "RHS_HSED22",
                    "RHS_HSED23",
                    "RHS_HSED24",
                    "RHS_HSED25",
                    "RHS_HSED26",
                    "RHS_HSED28",
                    "RHS_HSED29",
                    "RHS_WOO"
                ]
            },
            "partnerNetFlag": false
        },
        "idBuilding": 131767,
        "languageRegion": "DE",
        "longText": "An Ihrem Standort ist bereits alles vorbereitet. Melden Sie sich jetzt online an und schon in wenigen Tagen k\u00f6nnen Sie vom gew\u00fcnschten Produkt profitieren.",
        "mobile": {
            "available": true,
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "ALL"
                ]
            },
            "partnerNetFlag": false
        },
        "vod": {
            "available": true,
            "houseUpgradeNeeded": false,
            "packages": {
                "_package": [
                    "BM_VODKIT"
                ]
            },
            "partnerNetFlag": false
        }
    },
    "availabilityResultState": "availabilityFound"
}

(Lesbar gemacht mit Google Chrome unter die Haube schauen (und JSON lesbar ausgeben))

Einige Erkenntnisse:

  • Diese API rechnet Strassenanschriften ins Schweizer Koordinatensystem um (600:200, irgendjemand?).
  • Das JSON sagt auch, wann das Gebäude an das cablecom-Netz angeschlossen wurde (Internet am 5. September 2000, Fernsehen am 1. Januar 1999 (wahrscheinlich ein Dummy-Wert, oder aber cablecom hat zu dem Stichtag das Berner Kabelnetz übernommen?)).
  • Benötigt mein Gebäude ein Upgrade? Aus meiner Sicht ein möglicher Hinweis auf Probleme in der Hausverkabelung und somit auf mögliche Geschwindigkeitseinbussen.
  • Es gibt drei Produktekategorien: dtv steht für Digital TV, hs steht für Highspeed (Internet) und dp wohl für Digital Phone.
  • Für jede Produktkategorie wird fein säuberlich aufgelistet, welche Packages verfügbar sind. Leider ist es mir nicht möglich, die Abkürzungen dieser Packages zu entziffern. Bei Digital TV vermute ich, dass einzelne Sender aufgelistet werden. Bei Highspeed Internet könnten es die effektiv verfügbaren Geschwindigkeiten sein.
  • Im JSON sind auch der Activation Code und die Setup ID aufgeführt, die man auf der Horizon-Box oder dem TV-Gerät für die Kanalsuche eingeben muss.
  • Schlussendlich sieht man auch, ob ein Gebäude an das (upc?) Glasfasernetz angeschlossen ist.

Tags: , , , , , ,
Labels: IT, Schweiz, Shopping

Keine Kommentare | neuen Kommentar verfassen

Donnerstag, 10. Juli 2014

Mit Python URLs dekodieren und JSON schön ausgeben

Ausgehend von dieser haarsträubenden URL der Credit Suisse …

https://www.credit-suisse.com/who_we_are/de/office_locator.jsp#%7B%22fs%22%3A%7B%22cid%22%3Anull%2C%22prid%22%3Anull%2C%22plid%22%3Anull%2C%22sid%22%3Anull%2C%22d%22%3A%5B0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%5D%7D%2C%22ms%22%3A%7B%22c%22%3A%7B%22lat%22%3A46.94739121310314%2C%22lng%22%3A7.44410902261734%7D%2C%22z%22%3A18%7D%2C%22mk%22%3A%7B%22id%22%3A4451%7D%2C%22is%22%3A%7B%22id%22%3A%22mapPanel%22%2C%22ps%22%3A%7B%22id%22%3A4451%2C%22sid%22%3A11613%2C%22segid%22%3Anull%2C%22d%22%3A%5B0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%5D%7D%7D%7D

… nachfolgend zwei Python Code-Snippets, mit welchen ihr die URL menschenlesbar machen könnt:

URLs dekodieren

urlClean = urllib.unquote(urlRaw).decode('utf8')

JSON schön ausgeben

json.dumps(json.loads(strJson), sort_keys=True, indent=4, separators=(',', ': '))

Tags: , , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Donnerstag, 10. Juli 2014

Öffnungszeiten Credit Suisse Bern-Bundesplatz

Da das Standortverzeichnis meiner Hausbank seit Jahr und Tag ein Usability-Nightmare ist, lege ich hier den Link ab, der mich direkt zu den Öffnungszeiten der Credit Suisse Bern-Bundesplatz führt:

Credit Suisse AG, Bern, Bundesplatz 2, Schweiz – Privatkunden

Falls ein Webmaster der Grossbank bei diesem Artikel vorbeischauen sollte, hier einige Anregungen:

  • Bitte das Standortverzeichnis mit — aus eurer Sicht — exotischen Browsern wie Apple Safari testen.
  • Bei diesen Tests solltet ihr am Besten auf den Google Maps fokussieren: Habe ich mich mit Safari auf Bern reingezoomt und klicke Bern–Bundesplatz an, springt die Karte wieder auf die Weltansicht und das Zoomen kann von vorne beginnen …
  • Die Verzögerung von 1-2 Sekunden nach der Auswahl eines Drop-Down-Elements ist Web 0.1, nicht Web 2.0 (ich glaube ich muss einen unfocus-Event generieren)
  • Wieso muss ich mich überhaupt wie ein Idiot durch vier Drop-Downs durchhangeln? Ist das State of the Art-Usability von 2014?
  • Wieso gibt es kein Suchfeld mit Autovervollständigung, in welches ich bspw. „Bundesplatz“ eingeben kann?
  • Wieso wird die URL nicht aktualisiert und wird eindeutig, wenn ich mich durch die Drop-Downs durchgekämpft habe und eine Filiale ausgewählt habe? Eine URL, welche ich als Lesezeichen ablegen kann und welche mich beim nächsten Aufruf direkt zu dem gewünschten Standort bringt?

Stattdessen übermittelt ihr in der URL solches URL-encodiertes JSON-Gefrickel:

https://www.credit-suisse.com/who_we_are/de/office_locator.jsp#%7B%22fs%22%3A%7B%22cid%22%3Anull%2C%22prid%22%3Anull%2C%22plid%22%3Anull%2C%22sid%22%3Anull%2C%22d%22%3A%5B0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%5D%7D%2C%22ms%22%3A%7B%22c%22%3A%7B%22lat%22%3A46.94739121310314%2C%22lng%22%3A7.44410902261734%7D%2C%22z%22%3A18%7D%2C%22mk%22%3A%7B%22id%22%3A4451%7D%2C%22is%22%3A%7B%22id%22%3A%22mapPanel%22%2C%22ps%22%3A%7B%22id%22%3A4451%2C%22sid%22%3A11613%2C%22segid%22%3Anull%2C%22d%22%3A%5B0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%5D%7D%7D%7D

… was auf Gut Deutsch lautet:

{
    "fs": {
        "cid": null,
        "d": [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
        ],
        "plid": null,
        "prid": null,
        "sid": null
    },
    "is": {
        "id": "mapPanel",
        "ps": {
            "d": [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ],
            "id": 4451,
            "segid": null,
            "sid": 11613
        }
    },
    "mk": {
        "id": 4451
    },
    "ms": {
        "c": {
            "lat": 46.94739121310314,
            "lng": 7.44410902261734
        },
        "z": 18
    }
}

Bravo, ihr habt gerade JSON-over-URL JoU erfunden!

Tags: , , , , , , , , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

Den Netatmo PHP API-Client mit weniger strikten SSL-Anforderungen patchen

Vor einigen Tagen hörte mein Raspberry Pi-Dashboard auf, die Werte meiner Netatmo NWS01 Wetterstation für Apple iPhone und Android anzuzeigen.

Auf meinem lokalen Mac funktionierte das Dashboard hingegen problemlos; d.h. ich konnte mittels dem Netatmo PHP API-Client die JSON-Datei mit den aktuellen Messwerten wie Temperatur, Luftdruck und -feuchtigkeit abrufen.

Die genaue Ursache hinter dem Problem kenne ich bis heute nicht, doch ich vermute mit dem jetzigen Wissensstand, dass die Cyon-Ingenieure an der Konfiguration ihrer Server herumgewerkelt haben und dabei unter anderem das Root-Zertifikat entfernt haben, welches der Netatmo API-Client zur HTTPS-verschlüsselten Kommunikation mit den Netatmo-Servern verwendet.

Nachdem ich nämlich die Exception mittels vardump() genauer betrachtete, welche NACurlErrorType zurücklieferte, war der Fall schnell sonnenklar:

...
[message:protected] => SSL peer certificate or SSH remote key was not OK
...

Nun … gut! Was macht man da? Ich habe die Datei NAApiClient.php gepatcht, indem ich cURL mit der auf false gesetzten Option CURLOPT_SSL_VERIFYHOST sage, unverifizierte SSL-Zertifikate kommentarlos zu akzeptieren:

...
        else 
        {
            $opts[CURLOPT_HTTPHEADER] = array('Expect:');
        }
        
        $opts[CURLOPT_SSL_VERIFYHOST] = false;
        
        curl_setopt_array($ch, $opts);
...

Bei einer API wie Netatmo ist diese manuell herbeigeführte Schwachstelle zu verantworten. Ginge es um Mailverkehr oder Online-Banking, würde ich eine solche Option definitiv nicht aktivieren.

Tags: , , , , , , , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Freitag, 30. August 2013

Google Chrome unter die Haube schauen (und JSON lesbar ausgeben)

Hierzu haben die Google-Entwickler folgende URI erdacht:

chrome://net-internals/

Über diese Benutzeroberfläche lassen sich Daten auch im JSON-Format exportieren. Damit diese JSON-Daten auch für Menschen (einigermassen) lesbar werden, nimmt man Python zu Hilfe. Im nachfolgenden Beispiel gehen wir davon aus, dass der JSON-Dump in der Datei dump.json abgelegt ist:

python -mjson.tool < dump.json > dump-pretty.json

Tags: , , , , , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen