1: <?php
2:
3: namespace Budabot\Core;
4:
5: 6: 7: 8: 9:
10: class MMDBParser {
11: private $mmdb = array();
12: private $file;
13:
14: private $logger;
15:
16: public function __construct($file) {
17: $this->file = $file;
18: $this->logger = new LoggerWrapper('MMDBParser');
19: }
20:
21: public function getMessageString($categoryId, $instanceId) {
22:
23: if (isset($this->mmdb[$categoryId][$instanceId])) {
24: return $this->mmdb[$categoryId][$instanceId];
25: }
26:
27: $in = $this->openFile();
28: if ($in === null) {
29: return null;
30: }
31:
32:
33:
34: $category = $this->findEntry($in, $categoryId, 8);
35: if ($category === null) {
36: $this->logger->log('error', "Could not find categoryID: '{$categoryId}'");
37: fclose($in);
38: return null;
39: }
40:
41:
42: $instance = $this->findEntry($in, $instanceId, $category['offset']);
43: if ($instance === null) {
44: $this->logger->log('error', "Could not find instance id: '{$instanceId}' for categoryId: '{$categoryId}'");
45: fclose($in);
46: return null;
47: }
48:
49: fseek($in, $instance['offset']);
50: $message = $this->readString($in);
51: $this->mmdb[$categoryId][$instanceId] = $message;
52:
53: fclose($in);
54:
55: return $message;
56: }
57:
58: public function findAllInstancesInCategory($categoryId) {
59: $in = $this->openFile();
60: if ($in === null) {
61: return null;
62: }
63:
64:
65:
66: $category = $this->findEntry($in, $categoryId, 8);
67: if ($category === null) {
68: $this->logger->log('error', "Could not find categoryID: '{$categoryId}'");
69: fclose($in);
70: return null;
71: }
72:
73: fseek($in, $category['offset']);
74:
75:
76: $instances = array();
77: $instance = $this->readEntry($in);
78: while ($previousInstance == null || $instance['id'] > $previousInstance['id']) {
79: $instances[] = $instance;
80: $previousInstance = $instance;
81: $instance = $this->readEntry($in);
82: }
83:
84: fclose($in);
85:
86: return $instances;
87: }
88:
89: public function getCategories() {
90: $in = $this->openFile();
91: if ($in === null) {
92: return null;
93: }
94:
95:
96: fseek($in, 8);
97:
98:
99: $categories = array();
100: $category = $this->readEntry($in);
101: while ($previousCategory == null || $category['id'] > $previousCategory['id']) {
102: $categories[] = $category;
103: $previousCategory = $category;
104: $category = $this->readEntry($in);
105: }
106:
107: fclose($in);
108:
109: return $categories;
110: }
111:
112: private function openFile($filename = "data/text.mdb") {
113: $in = fopen($filename, 'rb');
114: if (!$in) {
115: $this->logger->log('error', "Could not open file: '{$filename}'");
116: fclose($in);
117: return null;
118: }
119:
120:
121: $entry = $this->readEntry($in);
122: if ($entry['id'] != 1111772493) {
123: $this->logger->log('error', "Not an mmdb file: '{$filename}'");
124: fclose($in);
125: return null;
126: }
127:
128: return $in;
129: }
130:
131: private function findEntry($in, $id, $offset) {
132: fseek($in, $offset);
133:
134: do {
135: $previousEntry = $entry;
136: $entry = $this->readEntry($in);
137:
138: if ($previousEntry != null && $entry['id'] < $previousEntry['id']) {
139: return null;
140: }
141: } while ($id != $entry['id']);
142:
143: return $entry;
144: }
145:
146: 147: 148:
149: private function readEntry($in) {
150: return array('id' => $this->readLong($in), 'offset' => $this->readLong($in));
151: }
152:
153: private function readLong($in) {
154: return array_pop(unpack("L", fread($in, 4)));
155: }
156:
157: private function readString($in) {
158: $message = '';
159: $char = '';
160:
161: $char = fread($in, 1);
162: while ($char !== "\0") {
163: $message .= $char;
164: $char = fread($in, 1);
165: }
166:
167: return $message;
168: }
169: }
170: