sabato 3 maggio 2025

Published maggio 03, 2025 by Django Faiola with 0 comment

iOS BeReal - Photos & Friends Daily (Cache.db & EntitiesStore.sqlite)

Indice dei contenuti

Introduzione

Questo secondo articolo è un approfondimento dell'analisi di BeReal focalizzato principalmente sul database SQLite Cache.db presente nell'Internal App Path "/Library/Caches/AlexisBarreyat.BeReal/", la cache.

Durante l'analisi condotta nel precedente articolo iOS BeReal - Photos & Friends Daily, ho postato diversi BeReal mentre ascoltavo la musica con Spotify per ricostruire l'object music del JSON, ma non ho trovato alcun riferimento negli stessi mentre nelle risposte alle richieste API nel database Cache.db sono presenti.

Un nuovo "attore è entrato in scena", il database EntitiesStore.sqlite presente nell'Internal App Group Path "/" del contenitore di gruppo  condiviso "/private/var/mobile/Containers/Shared/AppGroup/<APP_GUID>". In realtà questo database SQLite era già presente da qualche versione, ma non popolato e in continuo aggiornamento. Una nuova banca dati ricca di informazioni: utenti, post, commenti, realmoji etc.

BeReal è un social network francese lanciato nel 2020 da Alexis Berreyat e Kevin Per maggiori dettagli sulle funzionalità dell'app consulta https://bereal.com.

App Store: https://apps.apple.com/us/app/bereal-photos-friends-daily/id1459645446

Per lo studio di questa app sono state utilizzate le versioni 4.0.0 (Dec 18, 2024) e successive fino alla 4.18.0 (Apr 14, 2025) del mio iPhone 8 iOS 16.7.10 test e quelle delle immagine pubbliche di Josh Hickman iOS 17.3, 16.1.2 e 15.3.1 con le rispettive versioni 2.24.0, 1.21.4 e 1.1.0.

Percorsi

Di seguito lo stralcio di BeReal del poster della SANS “iOS Third-Party Apps Forensics Reference Guide Poster” con le informazioni più rilevanti per l’analisi dell’app.

Cache.db

Una breve introduzione sul database Cache.db prima di iniziare l'analisi serve a chiarire i concetti che seguiranno. Questo database SQLite tiene traccia dei dati che l'app ha ricevuto da fonti esterne come un server o internet, una cache per velocizzare il caricamento se necessario. Due sono le tabelle principali di interesse:

  • cfurl_cache_response: contiene i dati e l'ora della richiesta;
  • cfurl_cache_receiver_data: contiene i dati ricevuti dal server in risposta alla richiesta al server tramite la tabella cfurl_cache_response.

Mettere in relazione queste tabelle è importante in quanto può fornire informazioni che non sono memorizzate altrove; ad esempio come detto precedentemente, i brani musicali ascoltati durante la pubblicazione del BeReal. Se la dimensione dei dati è di 4096 byte o superiore sono   memorizzati su file (cfurl_cache_response.isDataOnFs=1) con il nome dell'UUID assegnato al campo cfurl_cache_receiver_data.receiver_data, altrimenti sono memorizzati nel database (cfurl_cache_response.isDataOnFs=0) come BLOB.

Per prima cosa bisogna ricostruire le relazioni delle tabelle di questo database SQLite:

SELECT
  cr.request_key AS "URL",
  datetime(strftime("%s", cr.time_stamp), 'unixepoch') AS "timestamp",
  crd.isDataOnFS,
  crd.receiver_data AS "data"
FROM cfurl_cache_response AS "cr"
LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)

Non entro nel dettaglio delle tabelle, quello che maggiormente interessa sono i campi:

  • cfurl_cache_response.request_key (URL): è la stringa di richiesta al server;
  • cfurl_cache_receiver_data.isDataOnFS (isDataOnFS): indica che i dati sono 1=esterni su file, 0=incorporati nel campo data;
  • cfurl_cache_receiver_data.receiver_data (data): contiene i dati ricevuti o il nome del file presente nella sottocartella "fsCachedData".

Account

L'API di richiesta del profilo: https://mobile-l7.bereal.com/api/person/me

SELECT
    crd.entry_ID,
    cr.request_key AS "URL",
    crd.isDataOnFS,
    crd.receiver_data
FROM cfurl_cache_response AS "cr"
LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/person\/me$"

La risposta in JSON:

Per la visualizzazione ho usato dfDataViewer, il mio visualizzatore di (B)Plist, JSON(B), (B)XML, ASN.1, Protobuf, LevelDB, etc. ancora in fase di sviluppo e non pubblico.

L'object root:

  • createdAt2024-12-19T15:59:49.277Z (data di creazione nel formato ISO 8601 19 dicembre 2024 15:59:49);
  • type: USER (tipo di profilo USER=regular, REAL_BRAND=marchi e REAL_PERSON=celebrità);
  • fullnameDjango (nome completo);
  • usernamedjango.f (username/nickname);
  • profilePicture: (immagine del profilo)
    • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/profile/CBEd9NNTW-igELqojHxxx.webp (URL dell'immagine del profilo);
    • width1000 (larghezza in pixel);
    • height1000 (altezza in pixel);
  • gender: (identità di genere, ad es. MALE, FEMALE, etc.);
  • birthdate197x-08-1xT00:00:00.000Z (data di nascita/compleanno nel formato ISO 8601 1x agosto 197x);
  • biographyDigital Forensics Consultant (biografia);
  • countryCodeIT (codice paese);
  • regioneurope-west (zona);
  • locationFondi (LT) (luogo/indirizzo);
  • phoneNumber+393494955xxx (numero di telefono);
  • devices: (array di dispositivi)
    • [0].timezoneEurope/Rome (fuso orario);
    • [0].clientVersion4.1.1 (versione dell'app);
    • [0].deviceiPhone10,1 16.7.10 (id modello e versione iOS);
    • [0].deviceId6F3A454F-8C8D-408F-85E9-B5427D715xxx (UID del dispositivo);
  • isPrivatefalse (è un profilo privato?);
    • realmojis: (array di emoji creati con i selfie)
      • [0].emoji: 👍 (emoji);
      • [0].media: (informazioni sul media)
        • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/realmoji/JVgRDw52ClLUWdDe.webp (URL del RealMoji);
    • idLRHP7nD4UhfzEJacyRtuZE37txxx (identificatore univoco dell'account).

    Persone

    L'API di richiesta delle persone: https://mobile-l7.bereal.com/api/person/profiles/<UID>?withPost=true

    SELECT
        crd.entry_ID,
        cr.request_key AS "URL",
        crd.isDataOnFS,
        crd.receiver_data
    FROM cfurl_cache_response AS "cr"
    LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
    WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/person\/profiles\/[\w-]+\?"

    La risposta in JSON del mio amico Luigi:

    L'object root:

    • createdAt2024-12-29T11:17:27.724Z (data di creazione nel formato ISO 8601 29 dicembre 2024 11:17:27);
    • typeUSER (tipo di profilo USER=regular, REAL_BRAND=marchi e REAL_PERSON=celebrità);
    • fullnameLuigi (nome completo);
    • usernamelmsconos (username/nickname);
    • profilePicturenull (URL dell'immagine del profilo);
    • biographynull (biografia);
    • locationnull (luogo/indirizzo);
    • relationship: (dettagli della relazione);
      • status: accepted (richiesta accettata);
      • friendedAt2025-01-01T09:13:46.000Z (amici dal, nel formato ISO 8601 29 dicembre 2024 11:19:42);
      • commonFriends: (amici in comune);
        • total: 0 (numero di amici in comune);
    • links: (array di collegamenti)
      • [?].url: (URL);
      • [?].displayText: (testo visualizzato);
    • streakLength0 (numero di BeReal consecutivi postati quando si riceve la "notifica ⚠️È l'ora di BeReal ⚠️"; F.A.Q.);
    • beRealOfTheDay: (BeReal del giorno)
      • postExistsfalse (ci sono post?);
      • userPosts: (informazioni sui post)
        • posts: (array di post)
      • lastPostDate:  (data dell'ultimo post, nel formato ISO 8601);
      • momentId: (identificatore univoco del momento);
      • user: (dati dell'utente, ad es. id, username, etc.);
    • isPrivatefalse (è un profilo privato?);
    • idmDO7GN3gKaY7d8xTxujhQoY0cxxx (identificatore univoco della persona).

    I miei Amici

    L'API di richiesta delle persone: https://mobile-l7.bereal.com/api/relationships/friends/?page

    SELECT
        crd.entry_ID,
        cr.request_key AS "URL",
        crd.isDataOnFS,
        crd.receiver_data
    FROM cfurl_cache_response AS "cr"
    LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
    WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*?\.bereal\.com\/api\/relationships\/friends($|\/\?page)"

    La risposta in JSON del mio amico Luigi:

    L'array data:

    • [0].fullnameLuigi (nome completo);
    • [0].usernamelmsconos (username/nickname);
    • [0].profilePicturenull (URL dell'immagine del profilo);
    • [0].statusaccepted (richiesta accettata);
    • [0].idmDO7GN3gKaY7d8xTxujhQoY0cxxx (identificatore univoco).

    Richieste di amicizia

    L'API di richiesta di amicizia inviate e ricevute: https://mobile-l7.bereal.com/api/relationships/friend-requests/sent?page e https://mobile-l7.bereal.com/api/relationships/friend-requests/received?page

    SELECT
        crd.entry_ID,
        cr.request_key AS "URL",
        crd.isDataOnFS,
        crd.receiver_data
    FROM cfurl_cache_response AS "cr"
    LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
    WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/relationships\/friend-requests\/(received|sent)\?page"

    La risposta in JSON delle richieste inviate:

    L'array data:

    • [0].updatedAt2024-12-31T18:30:38.417Z (stato aggiornato alla data, nel formato ISO 8601 31 dicembre 2024 18:30:38);
    • [0].fullnameLuigi (nome completo);
    • [0].usernamelmsconos (username/nickname);
    • [0].statussent (richiesta inviata, oppure canceled se annullata);
    • [0].mutualFriends0 (amici in comune);
    • [0].idmDO7GN3gKaY7d8xTxujhQoY0cxxx (identificatore univoco).

    Le richieste di amicizia ricevute hanno la stessa struttura di quelle inviate, si differenziano sostanzialmente per il valore di status.

    • [0].statuspending (in attesa di conferma, oppure rejected se rifiutata);

    Utenti bloccati

    L'API di richiesta della lista degli utenti bloccati: https://mobile-l7.bereal.com/api/moderation/block-users?page

    SELECT
        crd.entry_ID,
        cr.request_key AS "URL",
        crd.isDataOnFS,
        crd.receiver_data
    FROM cfurl_cache_response AS "cr"
    LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
    WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/moderation\/block-users\?page"

    La risposta in JSON con la lista degli utenti bloccati:

    L'array data:

    • [0].blockedAt2024-12-29T14:16:03.180Z (data del blocco nel formato ISO 8601 29 dicembre 2024 14:16:03);
    • [0].fullnameLuigi (nome completo);
    • [0].usernamelmsconos (username/nickname);
    • [0].idmDO7GN3gKaY7d8xTxujhQoY0cxxx (identificatore univoco).

    Le tue Memorie

    L'API di richiesta della memorie personali: https://mobile-l7.bereal.com/api/feeds/memories-v2/<UID>

    SELECT
        crd.entry_ID,
        cr.request_key AS "URL",
        crd.isDataOnFS,
        crd.receiver_data
    FROM cfurl_cache_response AS "cr"
    LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
    WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/feeds\/memories-v(\d)+\/[\w-]+$"

    La risposta in JSON della memoria entry_ID=35:

    L'array posts (esempio post=0):

    • memoryDay2024-12-21 (data del ricordo nel formato YYYY-MM-DD 21 dicembre 2024);
    • [0].isLatefalse (il BeReal è successivo allo slot temporale di due minuti per postare?);
    • [0].isMain: true (il BeReal è quello principale? true=main, false=bonus);
    • [0].visibilities: (array di stringhe con la visibilità)
      • [0]friends (amici, ad es. friends=amici, friends-of-friends=amici di amici, public=pubblico);
    • [0].primary: (tipicamente la camera posteriore)
      • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/post/qRKzdxZ26Kgt1rVi.webp (URL del media);
      • mediaType: image (image=foto o video=video);
        • width1500 (larghezza dell'immagine);
        • height2000 (altezza dell'immagine);
      • [0].secondary: (selfie, stessa struttura del primary);
      • [0].thumbnail: (miniatura della primary, stessa struttura del primary)
        • urlhttps://cdn-us1.bereal.network/cdn-cgi/image/height=130/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/post/qRKzdxZ26Kgt1rVi.webp (URL della miniatura);
        • width97 (larghezza della miniatura);
        • height130 (altezza della miniatura);
        • mediaTypeimage;
      • [0].takenAt2024-12-21T18:39:46.927Z (data dello scatto nel formato ISO 8601 21 dicembre 2024 18:39:46);
      • [0].captionC.C. Aprilia2 (titolo);
      • [0].location: (coordinate del posto, se attiva la geo-localizzazione)
        • latitude??? (latitudine);
        • longitude??? (longitudine);
      • [0].comments: (array con commenti);
      • [0].realmojis: (array di emoji creati con i selfie);
      • [0].tags: (array di amici/persone taggate);
      • [0].idJqBYXSaKEoBK7G4-3Zxxx (identificatore univoco del BeReal).

      L'identificatore del ricordo/memoria è quello della richiesta API, nello specifico <UID>=RyKjYfWYDaqA4jql2SA9r (Moment ID).

      Nel caso di un BeReal con audio condiviso con Spotify versione Free, la struttura del music è la seguente:

      L'object music:

      • isrcITB007770537 (International Standard Recording Code è il codice identificativo della registrazione);
      • providerspotify (fornitore del servizio, ad es. spotify, apple per Apple Music? da verificare);
      • providerId: 0RbhVoxOZE8BniSgmDbaXV (identificativo della traccia musicale, ovvero il track_id);
      • visibility: public (visibilità pubblica).

      Nel caso di Spotify, seppur non avendo direttamente l'URL come nelle vecchie versioni di BeReal, ove è presente la chiave openUrl, è possibile riscostruire l'indirizzo della risorsa in uno dei due formati a seguire, entrambi validi:

      https://open.spotify.com/track/{track_id} (vecchio formato) e/o https://open.spotify.com/intl-it/track/{track_id} (nuovo formato).

      URL: https://open.spotify.com/track/0RbhVoxOZE8BniSgmDbaXV

      Purtroppo mancano le informazioni relative al nome dell'artista e al titolo del brano, almeno nel mio caso.

      Object music estrapolato dall'immagine pubblica di Josh Hickman iOS 15.3.1 con la versione 1.1.0:


      Come si può vedere, è presente il nome dell'artista, il titolo del brano, l'immagine dell'album e l'URL del brano di Spotify.

      BeReal appuntati

      L'API di richiesta della memorie personali: https://mobile-l7.bereal.com/api/feeds/memories-v1/pinned-memories/for-user/<UID>

      SELECT
          crd.entry_ID,
          cr.request_key AS "URL",
          crd.isDataOnFS,
          crd.receiver_data
      FROM cfurl_cache_response AS "cr"
      LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
      WHERE cr.request_key REGEXP "https:\/\/mobile[-\w]*\.bereal\.com\/api\/feeds\/memories-v(\d)+\/pinned-memories\/for-user\/[\w-]+$"

      La risposta in JSON della memoria entry_ID=26:

      L'array pinnedMemories:

      • [0].takenAt2024-12-28T17:36:09.434Z (data di creazione nel formato ISO 8601 28 dicembre 2024 17:36:09);
      • [0].memoryDay2024-12-28 (data del momento del BeReal nel formato YYYY-MM-DD 28 dicembre 2024);
      • [0].primary: (fotocamera primaria, in genere quella posteriore)
        • mediaType: image (image=foto o video=video);
        • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/post/xfbzj038hsmlIEc0.webp (URL dell'immagine);
        • width1500 (larghezza dell'immagine);
        • height2000 (altezza dell'immagine);
      • [0].secondary: (fotocamera secondaria, in genere quella frontale)
        • mediaType: image (image=foto o video=video);
        • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/post/qKg3ejQRQIx_CP_R.webp (URL dell'immagine);
        • width1502 (larghezza dell'immagine);
        • height2000 (altezza dell'immagine);
      • [0].isLatefalse (il BeReal è successivo allo slot temporale di due minuti per postare?);
      • [0].isMaintrue (il BeReal è quello principale? true=main, false=bonus);
      • [0].momentIdW_FryMaPGgv9WIR1wF6GX (identificatore univoco della memoria);
      • [0].idJqBYXSaKEoBK7G4-3ZMpe (identificatore univoco del BeReal).

      L'autore del BeReal è quello della richiesta API, nello specifico <UID>=LRHP7nD4UhfzEJacyRtuZE37txxx (Django).

      L'indice dell'array indica la posizione del pin nella schermata: 0=primo elemento.

      Commenti sui BeReal

      I commenti come descritto nell'articolo precedente iOS BeReal - Photos & Friends Daily possono essere estrapolati da vari JSON: per la Cache.db, dai post delle memorie e delle persone.

      La risposta in JSON della memoria entry_ID=79:

      I commenti sul BeReal posts[i]l'array comments:

      • [0].postedAt2025-01-05T11:06:08.305Z (data del commento nel formato ISO 8601 05 gennaio 2025 11:06:08);
      • [0].user (informazioni sull'autore):
        • idLRHP7nD4UhfzEJacyRtuZE37txxx (identificativo univoco dell'autore);
        • usernamedjango.f (nome utente dell'autore);
        • typeUSER (tipo di profilo USER=regular, REAL_BRAND=marchi e REAL_PERSON=celebrità);
        • profilePicture: (immagine del profilo):
          • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/profile/CBEd9NNTW-igELqojHZm6.webp (URL dell'immagine del profilo dell'autore);
      • [0].contentTest commento semplice (testo);
      • [0].userIdLRHP7nD4UhfzEJacyRtuZE37txxx (identificativo univoco dell'autore);
      • [0].postId: Ta07G9ad8uTuGlmL-6KiX (identificatore univoco del BeReal);
      • [0].idzmd1UrmumdwRIcXK2pxxx (identificatore univoco del commento).

      La risposta in JSON della persona (vecchio archivio):

      I commenti sul BeReal beRealOfTheDay.userPosts.posts[1]l'array comments:

      • [1].postedAt2025-01-31T14:25:28.486Z (data del commento nel formato ISO 8601 31 gennaio 2025 14:25:28);
      • [1].user (informazioni sull'autore):
        • idLRHP7nD4UhfzEJacyRtuZE37txxx (identificativo univoco dell'autore);
        • usernamedjango.f (nome utente dell'autore);
        • typeUSER (tipo di profilo USER=regular, REAL_BRAND=marchi e REAL_PERSON=celebrità);
        • profilePicture: (immagine del profilo):
          • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/profile/CBEd9NNTW-igELqojHZm6.webp (URL dell'immagine del profilo dell'autore);
      • [1].contentIl pollice è del Talano 🤣 (testo);
      • beRealOfTheDay.userPosts.posts[1].idO8YAuxdnIVJRLTgE2Y470 (identificatore univoco del BeReal);
      • [1].idn1RlO5u7KyMaSKhtpWf-C (identificatore univoco del commento).

      RealMojis

      Discorso analogo ai commenti, i RealMojis possono essere estrapolati dai post delle persone e delle memorie.

      La risposta in JSON della persona (vecchio archivio):

      Le reazioni sul BeReal beRealOfTheDay.userPosts.posts[1]l'array realMojis:

      • [0].postedAt2025-01-31T14:24:55.795Z (data della reazione nel formato ISO 8601 31 gennaio 2025 14:24:55);
      • [0].emoji: 👍 (emoji);
      • [0].media: (informazioni sul selfie)
        • url: https://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/realmoji/JVgRDw52ClLUWdDe.webp (URI del RealMoji);
      • [0].user (informazioni sull'autore):
        • idLRHP7nD4UhfzEJacyRtuZE37txxx (identificativo univoco dell'autore);
        • usernamedjango.f (nome utente dell'autore);
        • typeUSER (tipo di profilo USER=regular, REAL_BRAND=marchi e REAL_PERSON=celebrità);
        • profilePicture: (immagine del profilo):
          • urlhttps://cdn-us1.bereal.network/Photos/LRHP7nD4UhfzEJacyRtuZE37txxx/profile/CBEd9NNTW-igELqojHZm6.webp (URL dell'immagine del profilo dell'autore);
      • [0].id: AabwT3kVJva-4kfsqVxxx (identificatore univoco del RealMoji).

      La risposta in JSON della memoria differisce di poco dalla precedente e comunque per avere un visione completa delle strutture, basta fare riferimento al modulo BeReal.py del progetto iLEAPP.

      EntitiesStore.sqlite

      Come anticipato nell'introduzione, durante l'analisi della cache delle varie estrazioni, ho tenuto d'occhio questo database EntitiesStore.sqlite; seppur non popolato, dall'ispezione della struttura era indubbia la bontà del suo valore.

      Di seguito sono riportate solo le query con i risultati.

      Account

      SELECT
          U.Z_PK AS "U_PK",
          U.ZPROFILETYPE,
          U.ZFULLNAME,
          U.ZUSERNAME,
          U.ZPROFILEPICTUREURL,
          U.ZBIO,
          U.ZID
      FROM ZUSERMO AS "U"
      WHERE U.ZID = "LRHP7nD4UhfzEJacyRtuZE37txxx"

      Amici

      SELECT
          U.Z_PK AS "U_PK",
          U.ZPROFILETYPE,
          U.ZFULLNAME,
          U.ZUSERNAME,
          U.ZPROFILEPICTUREURL,
          U.ZBIO,
          U.ZID
      FROM ZUSERMO AS "U"
      WHERE U.ZID != "LRHP7nD4UhfzEJacyRtuZE37txxx"

      Post

      SELECT
          U.Z_PK AS "U_PK",
          P.Z_PK AS "P_PK",
          U.Z_PK AS "U_PK",
          PM.Z_PK AS "PM_PK",
          SM.Z_PK AS "SM_PK",
          PTM.Z_PK AS "PTM_PK",
          STM.Z_PK AS "STM_PK",
          M.Z_PK AS "M_PK",
          L.Z_PK AS "L_PK",
          datetime(P.ZTAKENAT + 978307200, 'unixepoch') AS "taken_at",
          P.ZISMAIN AS "is_main",
          CASE
              WHEN P.ZISLATE = 0 AND P.ZISMAIN = 1 THEN "onTime"
              WHEN P.ZISLATE = 1 AND P.ZISMAIN = 1 THEN "late"
              WHEN P.ZISLATE = 0 AND P.ZISMAIN = 0 THEN "onTime bonus"
              WHEN P.ZISLATE = 1 AND P.ZISMAIN = 0 THEN "late bonus"
          END AS "case_type",
          U.ZID || " (" || coalesce(U.ZFULLNAME, U.ZUSERNAME) || ")" AS "author",
          PM.ZMEDIATYPE AS "pm_type",
          PM.ZURL AS "pm_url",
          SM.ZMEDIATYPE AS "sm_type",
          SM.ZURL AS "sm_url",
          PTM.ZMEDIATYPE AS "ptm_type",
          PTM.ZURL AS "ptm_url",
          STM.ZMEDIATYPE AS "stm_type",
          STM.ZURL AS "stm_url",
          M.ZARTIST || " - " || M.ZTRACK AS "song_title",
          M.ZOPENURL AS "song_url",
          P.ZCAPTION,
          L.ZLATITUDE,
          L.ZLONGITUDE,
          P.ZRETAKECOUNTER,
          P.ZLATEINSECONDS,
          P.ZVISIBILITIES,
          (P.ZRESHAREDFROM > 0) AS "reshared",
          --tagged friends
          P.ZMOMENTID,
          P.ZID AS "bereal_id"
      FROM ZPOSTMO AS "P"
      LEFT JOIN ZUSERMO AS "U" ON (P.ZUSER = U.Z_PK)
      LEFT JOIN ZPOSTMO_MEDIAMO AS "PM" ON (P.ZPRIMARYMEDIA = PM.Z_PK)
      LEFT JOIN ZPOSTMO_MEDIAMO AS "SM" ON (P.ZSECONDARYMEDIA = SM.Z_PK)
      LEFT JOIN ZPOSTMO_MEDIAMO AS "PTM" ON (P.ZPRIMARYTHUMBNAIL = PTM.Z_PK)
      LEFT JOIN ZPOSTMO_MEDIAMO AS "STM" ON (P.ZSECONDARYTHUMBNAIL = STM.Z_PK)
      LEFT JOIN ZPOSTMO_MUSICMO AS "M" ON (P.ZMUSIC = M.Z_PK)
      LEFT JOIN ZPOSTMO_LOCATIONMO AS "L" ON (P.ZLOCATION = L.Z_PK)

      Da evidenziare, che per quanto riguarda l'object music, in questo database è presente la tabella ZPOSTMO_MUSICMO con tutti i dettagli dell'audio.

      Commenti

      SELECT
          C.Z_PK AS "C_PK",
          P.Z_PK AS "P_PK",
          U.Z_PK AS "U_PK",
          datetime(C.ZCREATIONDATE + 978307200, 'unixepoch') AS "created_at",
          P.ZID AS "bereal_id",
          IIF(U.ZID = C.ZUSERID, "Outgoing", "Incoming") AS "direction",
          U.ZID || " (" || U.ZUSERNAME || ")" AS "owner",
          C.ZUSERID || " (" || C.ZUSERNAME || ")" AS "author",
          C.ZTEXT,
          P.ZMOMENTID AS "moment_id",
          C.ZID AS "comment_id"
      FROM ZPOSTMO_COMMENTMO AS "C"
      LEFT JOIN ZPOSTMO AS "P" ON (C.ZPOST = P.Z_PK)
      LEFT JOIN ZUSERMO AS "U" ON (P.ZUSER = U.Z_PK)

      RealMojis

      SELECT
          R.Z_PK AS "R_PK",
          P.Z_PK AS "P_PK",
          U.Z_PK AS "U_PK",
          datetime(R.ZDATE + 978307200, 'unixepoch') AS "reaction_date",
          P.ZID AS "bereal_id",
          IIF(U.ZID = R.ZUSERID, "Outgoing", "Incoming") AS "direction",
          U.ZID || " (" || U.ZUSERNAME || ")" AS "owner",
          R.ZUSERID || " (" || R.ZUSERNAME || ")" AS "author",
          R.ZEMOJI,
          R.ZURL,
          P.ZMOMENTID AS "moment_id",
          R.ZID AS "realmoji_id"
      FROM ZPOSTMO_REALMOJIMO AS "R"
      LEFT JOIN ZPOSTMO AS "P" ON (R.ZPOST = P.Z_PK)
      LEFT JOIN ZUSERMO AS "U" ON (P.ZUSER = U.Z_PK)

      Non ho dettagliato la descrizione dei campi in quanto sono stati già ampiamente descritti sia sopra che nel precedente articolo. Per maggiori dettagli invito sempre tutti a dare un'occhiata al codice BeReal.py.

      Da fare

      Resta sempre sospesa la struttura degli screenshot 😡. Ho postato dei BeReal pubblici, se qualcuno vuole contribuire alla ricerca, è libero di fare lo screenshot 🙏. Il mio link https://bere.al/django.f.

      iLEAPP 💖

      Come di consueto, sempre a supporto del progetto iLEAPP (iOS Logs, Events, And Plists Parser) di Alexis Brignoni ho aggiornato il plugin BeReal.py che alla data odierna è in “pull request” e comunque disponibile sul mio GitHub.

      Di seguito alcuni screenshot del report di BeReal:

      0 comments:

      Posta un commento