iphone-4smsIch habe mich der Sache mit meinem Fehlerhaften SMS-Speicher nochmals angenommen. Offensichtlich bin ich nicht der Einzige, der damit Probleme hat, siehe Apple Forum.

Eine Chance zur Reparatur hat man sowieso nur, wenn man ein offenes iPhone (Jailbreak) hat und ein sshd installiert ist. Damit habe ich mir mal die SQLite-Datenbank sms.db aus

/var/mobile/Library/SMS/sms.db

wegkopiert und analysiert. Die SMS-Nachrichten selbst landen in der Tabelle “message”. Zusätzlich gibt es noch eine Tabelle “msg_group”, in der eine Zusammenfassung über die verwalteten SMS abgelegt ist. Hier ist nach den Message-Centern sortiert die Anzahl der offenen SMS eingetragen. Aus dem Trigger “delete_message” der Tabelle “message” läßt sich erkennen, dass die Anzahl der gelesenen SMS in “msg_group” immer um -1 reduziert wird. Das kann natürlich ab und an zu den Fehlern führen, wie ich sie habe.

Wichtig: Vor Änderungen bitte

  • ein Backup ziehen
  • die SIM deaktivieren oder herausnehmen, damit keine eingehende SMS das Prozedere stört
  • unter “Einstellungen” – “Allgemein” – “Automatische Sperre” auf “Nie” setzen!

Ein update auf “msg_group” hilft hier schon einmal:

sqlite3 /var/mobile/Library/SMS/sms.db
sqlite> update msg_group set unread_count=0; 

Das Problem ist nur, dass es in der Datenbank immer noch Einträge gibt, die als nicht gelesen markiert sind:

sqlite> select * from message where read<>1;
sqlite> delete from message where read<>1;
SQL error: no such function: read

Aha. Beim Feld “read” handelt es sich anscheinend um ein Bitmap, dessen zweites Bit das Flag “read” darstellt. Nach langem suchen habe ich ein Script gefunden, das alle SMS pauschal löscht. Zwei kleine Anpassungen (fett) und schon klappts sowohl mit iPhone OS 3.0 als auch mit den “defekten” Nachrichten:

#! /usr/bin/python
from sqlite3 import dbapi2 as sqlite
def message_read(flags):
"""reimplementation of an sqlite user defined
function called by a trigger on the messages table.
the trigger checks the message flags to see if a
message has been read to see if the counter of
unread messages in another needs to be updated when
a message is deleted.
"""
# second bit is the "was read" flag
return (int(flags) & 0x02) >> 1
db = sqlite.connect('/var/mobile/Library/SMS/sms.db')
# register the user-defined function used by delete trigger
db.create_function('read', 1, message_read)
c = db.cursor()
c.execute('delete from message where read<>1;')
c.execute('update msg_group set unread_count=0;')

db.commit()
# vim:set ts=4 sw=4 ai et tw=80:

Es gibt inzwischen auch eine eine App “SMSFix” aus dem Cydia-Repository, die hat bei mir allerdings nicht funktioniert.

Weitere Quellen: toofisches.net, sukkology.net