1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
using Xmpp;
using Gee;
using Dino.Entities;
using Dino.Qlite;
namespace Dino {
public class FileTransferStorage : StreamInteractionModule, Object {
public static ModuleIdentity<FileTransferStorage> IDENTITY = new ModuleIdentity<FileTransferStorage>("file_store");
public string id { get { return IDENTITY.id; } }
private StreamInteractor stream_interactor;
private Database db;
private WeakMap<int, FileTransfer> files_by_db_id = new WeakMap<int, FileTransfer>();
private WeakMap<int, FileTransfer> files_by_message_id = new WeakMap<int, FileTransfer>();
private WeakMap<int, FileTransferGroup> file_group_by_db_id = new WeakMap<int, FileTransferGroup>();
private WeakMap<int, FileTransferGroup> file_group_by_message_id = new WeakMap<int, FileTransferGroup>();
private WeakMap<string, FileTransfer> files_by_message_and_file_id = new WeakMap<string, FileTransfer>();
public static void start(StreamInteractor stream_interactor, Database db) {
FileTransferStorage m = new FileTransferStorage(stream_interactor, db);
stream_interactor.add_module(m);
}
private FileTransferStorage(StreamInteractor stream_interactor, Database db) {
this.stream_interactor = stream_interactor;
this.db = db;
}
public void add_file(FileTransfer file_transfer) {
file_transfer.persist(db);
cache_file(file_transfer);
}
public void add_file_group(FileTransferGroup file_group) {
file_group.persist(db);
cache_file_group(file_group);
}
// `conversation` should be provided, otherwise the FileTransfer.ourpart might be wrong
public FileTransfer? get_file_by_id(int id, Conversation? conversation) {
FileTransfer? file_transfer = files_by_db_id[id];
if (file_transfer != null) {
return file_transfer;
}
RowOption row_option = db.file_transfer.select().with(db.file_transfer.id, "=", id).row();
return create_file_from_row_opt(row_option, conversation);
}
// Http file transfers store the corresponding message id in the `info` field
public FileTransfer? get_file_by_message_id(int id, Conversation conversation) {
FileTransfer? file_transfer = files_by_message_id[id];
if (file_transfer != null) {
return file_transfer;
}
RowOption row_option = db.file_transfer.select()
.with(db.file_transfer.info, "=", id.to_string())
.single()
.row();
return create_file_from_row_opt(row_option, conversation);
}
public FileTransferGroup? get_file_group_by_id(int id, Conversation conversation) {
FileTransferGroup? file_group = file_group_by_db_id[id];
if (file_group != null) {
return file_group;
}
RowOption row_option = db.file_transfer_group.select().with(db.file_transfer_group.id, "=", id).row();
return row_option.is_present() ? create_file_group_from_row(row_option.inner, conversation) : null;
}
public FileTransferGroup get_file_group_by_message_id(int id, Conversation conversation) {
FileTransferGroup? file_group = file_group_by_message_id[id];
if (file_group != null) {
return file_group;
}
foreach (Row row in db.file_transfer_group.select().with(db.file_transfer_group.message_id, "=", id)) {
return create_file_group_from_row(row, conversation);
}
return null;
}
public FileTransfer get_files_by_message_and_file_id(int message_id, string file_sharing_id, Conversation conversation) {
string combined_identifier = message_id.to_string() + file_sharing_id;
FileTransfer? file_transfer = files_by_message_and_file_id[combined_identifier];
if (file_transfer == null) {
RowOption row_option = db.file_transfer.select()
.with(db.file_transfer.info, "=", message_id.to_string())
.with(db.file_transfer.file_sharing_id, "=", file_sharing_id)
.single()
.row();
file_transfer = create_file_from_row_opt(row_option, conversation);
}
// There can be collisions in the combined identifier, check it's the correct FileTransfer
if (file_transfer != null && file_transfer.info == message_id.to_string() && file_transfer.file_sharing_id == file_sharing_id) {
return file_transfer;
}
return null;
}
private FileTransfer? create_file_from_row_opt(RowOption row_opt, Conversation? conversation) {
if (!row_opt.is_present()) return null;
try {
FileTransfer file_transfer = new FileTransfer.from_row(db, row_opt.inner, FileManager.get_storage_dir());
if (conversation != null && conversation.type_.is_muc_semantic()) {
file_transfer.ourpart = conversation.counterpart.with_resource(file_transfer.ourpart.resourcepart);
}
cache_file(file_transfer);
return file_transfer;
} catch (InvalidJidError e) {
warning("Got file transfer with invalid Jid: %s", e.message);
}
return null;
}
private FileTransferGroup? create_file_group_from_row(Row file_transfer_group_row, Conversation conversation) {
QueryBuilder query = db.file_transfer_group_file_transfer.select()
.with(db.file_transfer_group_file_transfer.file_transfer_group_id, "=", file_transfer_group_row[db.file_transfer_group.id]);
var file_transfers = new ArrayList<FileTransfer>();
foreach (Qlite.Row row in query) {
FileTransfer file_transfer = get_file_by_id(row[db.file_transfer_group_file_transfer.file_transfer_id], conversation);
file_transfers.add(file_transfer);
}
if (file_transfers.size == 0) return null;
FileTransferGroup file_group = new FileTransferGroup.from_row(db, file_transfer_group_row, file_transfers);
cache_file_group(file_group);
return file_group;
}
private void cache_file(FileTransfer file_transfer) {
files_by_db_id[file_transfer.id] = file_transfer;
if (file_transfer.info != null && file_transfer.info != "") {
files_by_message_id[int.parse(file_transfer.info)] = file_transfer;
if (file_transfer.file_sharing_id != null && file_transfer.info != null) {
string combined_identifier = file_transfer.info + file_transfer.file_sharing_id;
files_by_message_and_file_id[combined_identifier] = file_transfer;
}
}
}
private void cache_file_group(FileTransferGroup file_group) {
file_group_by_db_id[file_group.id] = file_group;
// file_group_by_message_id[file_group.message_id] = file_group;
}
}
}
|