-- Normalized httpd vhost
log -- Section 0. Decent defaults
PRAGMA page_size=4096;
PRAGMA default_cache_size=2048; -- = 8 MByte
PRAGMA cache_size=512;
PRAGMA foreign_keys=ON;
PRAGMA recursive_triggers=ON;
-- The table that would have been used for a 1:1 mapping of logfile to table
-- CREATE TABLE Loglines (
-- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
-- , id_log INTEGER
-- , linenr INTEGER
-- , vhost TEXT
-- , hhost TEXT
-- , client TEXT
-- , dtevent REAL
-- , method TEXT
-- , lpath TEXT
-- , lpage TEXT
-- , args TEXT
-- , rc INTEGER
-- , rsz INTEGER
-- , isz INTEGER
-- , osz INTEGER
-- );
-- Section 1. Referenced tables
-- 1.0
CREATE TABLE Categories (
id INTEGER PRIMARY KEY NOT NULL
, desc TEXT UNIQUE NOT NULL
);
INSERT INTO Categories (id,desc) VALUES (0,'unknown');
INSERT INTO Categories (id,desc) VALUES (1,'self');
INSERT INTO Categories (id,desc) VALUES (2,'meatwork');
INSERT INTO Categories (id,desc) VALUES (3,'family');
INSERT INTO Categories (id,desc) VALUES (4,'friend');
INSERT INTO Categories (id,desc) VALUES (5,'known');
INSERT INTO Categories (id,desc) VALUES (6,'hacker');
-- 1.1
CREATE TABLE Logs (
id INTEGER PRIMARY KEY NOT NULL
, filename TEXT UNIQUE NOT NULL
, dtimport REAL DEFAULT (julianday('now'))
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.2
CREATE TABLE Vhosts (
id INTEGER PRIMARY KEY NOT NULL
, vh TEXT UNIQUE NOT NULL -- abbreviation
, vhost TEXT UNIQUE NOT NULL -- full name_or_ip
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.3
CREATE TABLE Hhosts (
id INTEGER PRIMARY KEY NOT NULL
, hh TEXT NOT NULL -- abbreviation, may not be unique
, hhost TEXT UNIQUE NOT NULL -- full name_or_ip
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.4
CREATE TABLE Clients (
id INTEGER PRIMARY KEY NOT NULL
, client TEXT UNIQUE NOT NULL -- ipdotted
, ciip INTEGER
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.5
CREATE TABLE Users (
id INTEGER PRIMARY KEY NOT NULL
, user TEXT UNIQUE NOT NULL
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.6
CREATE TABLE Methods (
id INTEGER PRIMARY KEY NOT NULL
, method TEXT UNIQUE NOT NULL
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.7
CREATE TABLE Lpaths (
id INTEGER PRIMARY KEY NOT NULL
, lpath TEXT UNIQUE NOT NULL
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.8
CREATE TABLE Lpages (
id INTEGER PRIMARY KEY NOT NULL
, lpage TEXT UNIQUE NOT NULL
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- 1.9
CREATE TABLE Argss (
id INTEGER PRIMARY KEY NOT NULL
, args TEXT UNIQUE NOT NULL
, refcnt INTEGER DEFAULT 0 NOT NULL -- denormalized, maintained by trigger
-- , refchk INTEGER DEFAULT 0 -- denormalized, maintained by procedure
);
-- prepopulate with empty strings
INSERT INTO Vhosts (vh,vhost) VALUES ('','');
INSERT INTO Hhosts (hh,hhost) VALUES ('','');
INSERT INTO Hhosts (hh,hhost) VALUES ('_lo0','localhost');
INSERT INTO Hhosts (hh,hhost) VALUES ('_lo4','127.0.0.1');
INSERT INTO Hhosts (hh,hhost) VALUES ('_lo6','::1');
INSERT INTO Hhosts (hh,hhost) VALUES ('_wan','1.2.3.4');
INSERT INTO Hhosts (hh,hhost) VALUES ('_lan','192.168.1.55');
INSERT INTO Clients (client,ciip) VALUES ('',0);
INSERT INTO Users (user) VALUES ('');
INSERT INTO Users (user) VALUES ('-');
INSERT INTO Methods (method) VALUES ('');
INSERT INTO Lpaths (lpath) VALUES ('');
INSERT INTO Lpages (lpage) VALUES ('');
INSERT INTO Argss (args) VALUES ('');
-- Section 2. Referencing tables
-- The main
log table mostly references the details.
CREATE TABLE T_Events (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
, id_log INTEGER NOT NULL REFERENCES Logs (id) ON DELETE CASCADE ON UPDATE CASCADE
, linenr INTEGER NOT NULL
, id_vhost INTEGER NOT NULL REFERENCES Vhosts (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_hhost INTEGER NOT NULL REFERENCES Hhosts (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_client INTEGER NOT NULL REFERENCES Clients (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_user INTEGER NOT NULL REFERENCES Users (id) ON DELETE CASCADE ON UPDATE CASCADE
, dtevent REAL
, id_method INTEGER NOT NULL REFERENCES Methods (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_lpath INTEGER NOT NULL REFERENCES Lpaths (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_lpage INTEGER NOT NULL REFERENCES Lpages (id) ON DELETE CASCADE ON UPDATE CASCADE
, id_args INTEGER NOT NULL REFERENCES Argss (id) ON DELETE CASCADE ON UPDATE CASCADE
, rc INTEGER
, rsz INTEGER
, isz INTEGER
, osz INTEGER
);
CREATE INDEX idx_te_dt on T_Events(dtevent);
-- Section 3. Updatable view that replaces that table
-- The view itself
CREATE VIEW Loglines AS
SELECT
E.id
, id_log
, linenr
, V.vhost
, H.hhost
, C.client
, C.ciip
, U.user
, dtevent
, M.method
, L.lpath
, P.lpage
, A.args
, rc
, rsz
, isz
, osz
FROM T_Events AS E
INNER JOIN Vhosts AS V ON (V.id==E.id_vhost)
INNER JOIN Hhosts AS H ON (H.id==E.id_hhost)
INNER JOIN Clients AS C ON (C.id==E.id_client)
INNER JOIN Users AS U ON (U.id==E.id_user)
INNER JOIN Methods AS M ON (M.id==E.id_method)
INNER JOIN Lpaths AS L ON (L.id==E.id_lpath)
INNER JOIN Lpages AS P ON (P.id==E.id_lpage)
INNER JOIN Argss AS A ON (A.id==E.id_args);
-- The trigger that defers the insert into view to insert in events, with all pointers looked up and filled in.
CREATE TRIGGER io_ins_Loglines INSTEAD OF INSERT ON Loglines
FOR EACH ROW
BEGIN
INSERT INTO T_Events (
id_log
, linenr
, id_vhost
, id_hhost
, id_client
, id_user
, dtevent
, id_method
, id_lpath
, id_lpage
, id_args
, rc
, rsz
, isz
, osz) VALUES (
NEW.id_log
, NEW.linenr
, (SELECT id FROM Vhosts WHERE vhost==NEW.vhost)
, (SELECT id FROM Hhosts WHERE hhost==NEW.hhost)
, (SELECT id FROM Clients WHERE client==NEW.client)
, (SELECT id FROM Users WHERE user==NEW.user)
, NEW.dtevent
, (SELECT id FROM Methods WHERE method==NEW.method)
, (SELECT id FROM Lpaths WHERE lpath==NEW.lpath)
, (SELECT id FROM Lpages WHERE lpage==NEW.lpage)
, (SELECT id FROM Argss WHERE args==NEW.args)
, NEW.rc
, NEW.rsz
, NEW.isz
, NEW.osz);
END;
-- Triggers for updating reference counters
-- speeds up reporting, slows down updates
CREATE TRIGGER a_ins_events AFTER INSERT ON T_Events
FOR EACH ROW
BEGIN
UPDATE Logs SET refcnt = refcnt + 1 WHERE id = NEW.id_log;
UPDATE Vhosts SET refcnt = refcnt + 1 WHERE id = NEW.id_vhost;
UPDATE Hhosts SET refcnt = refcnt + 1 WHERE id = NEW.id_hhost;
UPDATE Clients SET refcnt = refcnt + 1 WHERE id = NEW.id_client;
UPDATE Users SET refcnt = refcnt + 1 WHERE id = NEW.id_user;
UPDATE Methods SET refcnt = refcnt + 1 WHERE id = NEW.id_method;
UPDATE Lpaths SET refcnt = refcnt + 1 WHERE id = NEW.id_lpath;
UPDATE Lpages SET refcnt = refcnt + 1 WHERE id = NEW.id_lpage;
UPDATE Argss SET refcnt = refcnt + 1 WHERE id = NEW.id_args;
END;
CREATE TRIGGER a_del_events AFTER DELETE ON T_Events
FOR EACH ROW
BEGIN
UPDATE Logs SET refcnt = refcnt - 1 WHERE id = OLD.id_log;
UPDATE Vhosts SET refcnt = refcnt - 1 WHERE id = OLD.id_vhost;
UPDATE Hhosts SET refcnt = refcnt - 1 WHERE id = OLD.id_hhost;
UPDATE Clients SET refcnt = refcnt - 1 WHERE id = OLD.id_client;
UPDATE Users SET refcnt = refcnt - 1 WHERE id = OLD.id_user;
UPDATE Methods SET refcnt = refcnt - 1 WHERE id = OLD.id_method;
UPDATE Lpaths SET refcnt = refcnt - 1 WHERE id = OLD.id_lpath;
UPDATE Lpages SET refcnt = refcnt - 1 WHERE id = OLD.id_lpage;
UPDATE Argss SET refcnt = refcnt - 1 WHERE id = OLD.id_args;
END;
CREATE VIEW Abbrevloglines AS
SELECT
E.id
, id_log
, linenr
, V.vh
, H.hh
, H.hhost
, C.client
, U.user
, dtevent
, M.method
, L.lpath
, rc
, rsz
, isz
, osz
FROM T_Events AS E
INNER JOIN Vhosts AS V ON (V.id==E.id_vhost)
INNER JOIN Hhosts AS H ON (H.id==E.id_hhost)
INNER JOIN Clients AS C ON (C.id==E.id_client)
INNER JOIN Users AS U ON (U.id==E.id_user)
INNER JOIN Methods AS M ON (M.id==E.id_method)
INNER JOIN Lpaths AS L ON (L.id==E.id_lpath);
-- Section 4. Any other tables
-- Dates, can be used as Integers as well
CREATE TABLE Dates (
id INTEGER PRIMARY KEY NOT NULL
, d REAL
);
CREATE TABLE KnownIPs (
ipdotted TEXT PRIMARY KEY NOT NULL
, owner TEXT DEFAULT 'knuyt'
, id_cat INTEGER NOT NULL DEFAULT 0 REFERENCES Categories (id) ON DELETE CASCADE ON UPDATE CASCADE
);
-- EOF
LS0gTm9ybWFsaXplZCBodHRwZCB2aG9zdCBsb2cKLS0gU2VjdGlvbiAwLiBEZWNlbnQgZGVmYXVsdHMKUFJBR01BIHBhZ2Vfc2l6ZT00MDk2OwpQUkFHTUEgZGVmYXVsdF9jYWNoZV9zaXplPTIwNDg7IC0tID0gOCBNQnl0ZQpQUkFHTUEgY2FjaGVfc2l6ZT01MTI7ClBSQUdNQSBmb3JlaWduX2tleXM9T047ClBSQUdNQSByZWN1cnNpdmVfdHJpZ2dlcnM9T047Ci0tICAgIFRoZSB0YWJsZSB0aGF0IHdvdWxkIGhhdmUgYmVlbiB1c2VkIGZvciBhIDE6MSBtYXBwaW5nIG9mIGxvZ2ZpbGUgdG8gdGFibGUKLS0JCUNSRUFURSBUQUJMRSBMb2dsaW5lcyAoCi0tCQkJaWQgICAgICAgICBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQgTk9UIE5VTEwKLS0JCSwJaWRfbG9nICAgICBJTlRFR0VSCi0tCQksCWxpbmVuciAgICAgSU5URUdFUgotLQkJLAl2aG9zdCAgICAgIFRFWFQKLS0JCSwJaGhvc3QgICAgICBURVhUCi0tCQksCWNsaWVudCAgICAgVEVYVAotLQkJLAlkdGV2ZW50ICAgIFJFQUwKLS0JCSwJbWV0aG9kICAgICBURVhUCi0tCQksCWxwYXRoICAgICAgVEVYVAotLQkJLAlscGFnZSAgICAgIFRFWFQKLS0JCSwJYXJncyAgICAgICBURVhUCi0tCQksCXJjICAgICAgICAgSU5URUdFUgotLQkJLAlyc3ogICAgICAgIElOVEVHRVIKLS0JCSwJaXN6ICAgICAgICBJTlRFR0VSCi0tCQksCW9zeiAgICAgICAgSU5URUdFUgotLQkJKTsKCi0tIFNlY3Rpb24gMS4gUmVmZXJlbmNlZCB0YWJsZXMKLS0gMS4wCkNSRUFURSBUQUJMRSBDYXRlZ29yaWVzICgKCWlkICAgICAgICAgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCWRlc2MgICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwKKTsKCklOU0VSVCBJTlRPIENhdGVnb3JpZXMgKGlkLGRlc2MpIFZBTFVFUyAoMCwndW5rbm93bicpOwpJTlNFUlQgSU5UTyBDYXRlZ29yaWVzIChpZCxkZXNjKSBWQUxVRVMgKDEsJ3NlbGYnKTsKSU5TRVJUIElOVE8gQ2F0ZWdvcmllcyAoaWQsZGVzYykgVkFMVUVTICgyLCdtZWF0d29yaycpOwpJTlNFUlQgSU5UTyBDYXRlZ29yaWVzIChpZCxkZXNjKSBWQUxVRVMgKDMsJ2ZhbWlseScpOwpJTlNFUlQgSU5UTyBDYXRlZ29yaWVzIChpZCxkZXNjKSBWQUxVRVMgKDQsJ2ZyaWVuZCcpOwpJTlNFUlQgSU5UTyBDYXRlZ29yaWVzIChpZCxkZXNjKSBWQUxVRVMgKDUsJ2tub3duJyk7CklOU0VSVCBJTlRPIENhdGVnb3JpZXMgKGlkLGRlc2MpIFZBTFVFUyAoNiwnaGFja2VyJyk7CgotLSAxLjEKQ1JFQVRFIFRBQkxFIExvZ3MgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCWZpbGVuYW1lICAgVEVYVCBVTklRVUUgTk9UIE5VTEwKLAlkdGltcG9ydCAgIFJFQUwgREVGQVVMVCAoanVsaWFuZGF5KCdub3cnKSkKLAlyZWZjbnQgICAgIElOVEVHRVIgREVGQVVMVCAwIE5PVCBOVUxMICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgdHJpZ2dlcgotLSAsCXJlZmNoayAgICAgSU5URUdFUiBERUZBVUxUIDAgICAgICAgICAgIC0tIGRlbm9ybWFsaXplZCwgbWFpbnRhaW5lZCBieSBwcm9jZWR1cmUKKTsKLS0gMS4yCkNSRUFURSBUQUJMRSBWaG9zdHMgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCXZoICAgICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwgICAgICAgIC0tIGFiYnJldmlhdGlvbgosCXZob3N0ICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwgICAgICAgIC0tIGZ1bGwgbmFtZV9vcl9pcAosCXJlZmNudCAgICAgSU5URUdFUiBERUZBVUxUIDAgTk9UIE5VTEwgIC0tIGRlbm9ybWFsaXplZCwgbWFpbnRhaW5lZCBieSB0cmlnZ2VyCi0tICwJcmVmY2hrICAgICBJTlRFR0VSIERFRkFVTFQgMCAgICAgICAgICAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHByb2NlZHVyZQopOwotLSAxLjMKQ1JFQVRFIFRBQkxFIEhob3N0cyAoCglpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIE5PVCBOVUxMCiwJaGggICAgICAgICBURVhUICAgICAgICBOT1QgTlVMTCAgICAgICAgLS0gYWJicmV2aWF0aW9uLCBtYXkgbm90IGJlIHVuaXF1ZQosCWhob3N0ICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwgICAgICAgIC0tIGZ1bGwgbmFtZV9vcl9pcAosCXJlZmNudCAgICAgSU5URUdFUiBERUZBVUxUIDAgTk9UIE5VTEwgIC0tIGRlbm9ybWFsaXplZCwgbWFpbnRhaW5lZCBieSB0cmlnZ2VyCi0tCSwJcmVmY2hrICAgICBJTlRFR0VSIERFRkFVTFQgMCAgICAgICAgICAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHByb2NlZHVyZQopOwotLSAxLjQKQ1JFQVRFIFRBQkxFIENsaWVudHMgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCWNsaWVudCAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwgICAgICAgIC0tIGlwZG90dGVkCiwJY2lpcCAgICAgICBJTlRFR0VSCiwJcmVmY250ICAgICBJTlRFR0VSIERFRkFVTFQgMCBOT1QgTlVMTCAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHRyaWdnZXIKLS0JLAlyZWZjaGsgICAgIElOVEVHRVIgREVGQVVMVCAwICAgICAgICAgICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgcHJvY2VkdXJlCik7Ci0tIDEuNQpDUkVBVEUgVEFCTEUgVXNlcnMgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCXVzZXIgICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwKLAlyZWZjbnQgICAgIElOVEVHRVIgREVGQVVMVCAwIE5PVCBOVUxMICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgdHJpZ2dlcgotLQksCXJlZmNoayAgICAgSU5URUdFUiBERUZBVUxUIDAgICAgICAgICAgIC0tIGRlbm9ybWFsaXplZCwgbWFpbnRhaW5lZCBieSBwcm9jZWR1cmUKKTsKLS0gMS42CkNSRUFURSBUQUJMRSBNZXRob2RzICgKCWlkIElOVEVHRVIgUFJJTUFSWSBLRVkgTk9UIE5VTEwKLAltZXRob2QgICAgIFRFWFQgVU5JUVVFIE5PVCBOVUxMCiwJcmVmY250ICAgICBJTlRFR0VSIERFRkFVTFQgMCBOT1QgTlVMTCAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHRyaWdnZXIKLS0JLAlyZWZjaGsgICAgIElOVEVHRVIgREVGQVVMVCAwICAgICAgICAgICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgcHJvY2VkdXJlCik7Ci0tIDEuNwpDUkVBVEUgVEFCTEUgTHBhdGhzICgKCWlkIElOVEVHRVIgUFJJTUFSWSBLRVkgTk9UIE5VTEwKLAlscGF0aCAgICAgIFRFWFQgVU5JUVVFIE5PVCBOVUxMCiwJcmVmY250ICAgICBJTlRFR0VSIERFRkFVTFQgMCBOT1QgTlVMTCAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHRyaWdnZXIKLS0JLAlyZWZjaGsgICAgIElOVEVHRVIgREVGQVVMVCAwICAgICAgICAgICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgcHJvY2VkdXJlCik7Ci0tIDEuOApDUkVBVEUgVEFCTEUgTHBhZ2VzICgKCWlkIElOVEVHRVIgUFJJTUFSWSBLRVkgTk9UIE5VTEwKLAlscGFnZSAgICAgIFRFWFQgVU5JUVVFIE5PVCBOVUxMCiwJcmVmY250ICAgICBJTlRFR0VSIERFRkFVTFQgMCBOT1QgTlVMTCAgLS0gZGVub3JtYWxpemVkLCBtYWludGFpbmVkIGJ5IHRyaWdnZXIKLS0JLAlyZWZjaGsgICAgIElOVEVHRVIgREVGQVVMVCAwICAgICAgICAgICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgcHJvY2VkdXJlCik7Ci0tIDEuOQpDUkVBVEUgVEFCTEUgQXJnc3MgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSBOT1QgTlVMTAosCWFyZ3MgICAgICAgVEVYVCBVTklRVUUgTk9UIE5VTEwKLAlyZWZjbnQgICAgIElOVEVHRVIgREVGQVVMVCAwIE5PVCBOVUxMICAtLSBkZW5vcm1hbGl6ZWQsIG1haW50YWluZWQgYnkgdHJpZ2dlcgotLQksCXJlZmNoayAgICAgSU5URUdFUiBERUZBVUxUIDAgICAgICAgICAgIC0tIGRlbm9ybWFsaXplZCwgbWFpbnRhaW5lZCBieSBwcm9jZWR1cmUKKTsKCi0tIHByZXBvcHVsYXRlIHdpdGggZW1wdHkgc3RyaW5ncwpJTlNFUlQgSU5UTyBWaG9zdHMgICh2aCx2aG9zdCkgICAgVkFMVUVTICgnJywnJyk7CklOU0VSVCBJTlRPIEhob3N0cyAgKGhoLGhob3N0KSAgICBWQUxVRVMgKCcnLCcnKTsKSU5TRVJUIElOVE8gSGhvc3RzICAoaGgsaGhvc3QpICAgIFZBTFVFUyAoJ19sbzAnLCdsb2NhbGhvc3QnKTsKSU5TRVJUIElOVE8gSGhvc3RzICAoaGgsaGhvc3QpICAgIFZBTFVFUyAoJ19sbzQnLCcxMjcuMC4wLjEnKTsKSU5TRVJUIElOVE8gSGhvc3RzICAoaGgsaGhvc3QpICAgIFZBTFVFUyAoJ19sbzYnLCc6OjEnKTsKSU5TRVJUIElOVE8gSGhvc3RzICAoaGgsaGhvc3QpICAgIFZBTFVFUyAoJ193YW4nLCcxLjIuMy40Jyk7CklOU0VSVCBJTlRPIEhob3N0cyAgKGhoLGhob3N0KSAgICBWQUxVRVMgKCdfbGFuJywnMTkyLjE2OC4xLjU1Jyk7CklOU0VSVCBJTlRPIENsaWVudHMgKGNsaWVudCxjaWlwKSBWQUxVRVMgKCcnLDApOwpJTlNFUlQgSU5UTyBVc2VycyAgICh1c2VyKSAgICAgICAgVkFMVUVTICgnJyk7CklOU0VSVCBJTlRPIFVzZXJzICAgKHVzZXIpICAgICAgICBWQUxVRVMgKCctJyk7CklOU0VSVCBJTlRPIE1ldGhvZHMgKG1ldGhvZCkgICAgICBWQUxVRVMgKCcnKTsKSU5TRVJUIElOVE8gTHBhdGhzICAobHBhdGgpICAgICAgIFZBTFVFUyAoJycpOwpJTlNFUlQgSU5UTyBMcGFnZXMgIChscGFnZSkgICAgICAgVkFMVUVTICgnJyk7CklOU0VSVCBJTlRPIEFyZ3NzICAgKGFyZ3MpICAgICAgICBWQUxVRVMgKCcnKTsKCi0tIFNlY3Rpb24gMi4gUmVmZXJlbmNpbmcgdGFibGVzCi0tICAgIFRoZSBtYWluIGxvZyB0YWJsZSBtb3N0bHkgcmVmZXJlbmNlcyB0aGUgZGV0YWlscy4KQ1JFQVRFIFRBQkxFIFRfRXZlbnRzICgKCWlkICAgICAgICAgICBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQgTk9UIE5VTEwKLAlpZF9sb2cgICAgICAgSU5URUdFUiBOT1QgTlVMTCBSRUZFUkVOQ0VTIExvZ3MgICAgKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSBPTiBVUERBVEUgQ0FTQ0FERQosCWxpbmVuciAgICAgICBJTlRFR0VSIE5PVCBOVUxMCiwJaWRfdmhvc3QgICAgIElOVEVHRVIgTk9UIE5VTEwgUkVGRVJFTkNFUyBWaG9zdHMgIChpZCkgT04gREVMRVRFIENBU0NBREUgT04gVVBEQVRFIENBU0NBREUKLAlpZF9oaG9zdCAgICAgSU5URUdFUiBOT1QgTlVMTCBSRUZFUkVOQ0VTIEhob3N0cyAgKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSBPTiBVUERBVEUgQ0FTQ0FERQosCWlkX2NsaWVudCAgICBJTlRFR0VSIE5PVCBOVUxMIFJFRkVSRU5DRVMgQ2xpZW50cyAoaWQpIE9OIERFTEVURSBDQVNDQURFIE9OIFVQREFURSBDQVNDQURFCiwJaWRfdXNlciAgICAgIElOVEVHRVIgTk9UIE5VTEwgUkVGRVJFTkNFUyBVc2VycyAgIChpZCkgT04gREVMRVRFIENBU0NBREUgT04gVVBEQVRFIENBU0NBREUKLAlkdGV2ZW50ICAgICAgUkVBTAosCWlkX21ldGhvZCAgICBJTlRFR0VSIE5PVCBOVUxMIFJFRkVSRU5DRVMgTWV0aG9kcyAoaWQpIE9OIERFTEVURSBDQVNDQURFIE9OIFVQREFURSBDQVNDQURFCiwJaWRfbHBhdGggICAgIElOVEVHRVIgTk9UIE5VTEwgUkVGRVJFTkNFUyBMcGF0aHMgIChpZCkgT04gREVMRVRFIENBU0NBREUgT04gVVBEQVRFIENBU0NBREUKLAlpZF9scGFnZSAgICAgSU5URUdFUiBOT1QgTlVMTCBSRUZFUkVOQ0VTIExwYWdlcyAgKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSBPTiBVUERBVEUgQ0FTQ0FERQosCWlkX2FyZ3MgICAgICBJTlRFR0VSIE5PVCBOVUxMIFJFRkVSRU5DRVMgQXJnc3MgICAoaWQpIE9OIERFTEVURSBDQVNDQURFIE9OIFVQREFURSBDQVNDQURFCiwJcmMgICAgICAgICAgIElOVEVHRVIKLAlyc3ogICAgICAgICAgSU5URUdFUgosCWlzeiAgICAgICAgICBJTlRFR0VSCiwJb3N6ICAgICAgICAgIElOVEVHRVIKKTsKCkNSRUFURSBJTkRFWCBpZHhfdGVfZHQgb24gVF9FdmVudHMoZHRldmVudCk7CgotLSBTZWN0aW9uIDMuIFVwZGF0YWJsZSB2aWV3IHRoYXQgcmVwbGFjZXMgdGhhdCB0YWJsZQotLSAgICBUaGUgdmlldyBpdHNlbGYKQ1JFQVRFIFZJRVcgTG9nbGluZXMgQVMgCiAgU0VMRUNUIAoJRS5pZAosCWlkX2xvZwosCWxpbmVucgosCVYudmhvc3QKLAlILmhob3N0CiwJQy5jbGllbnQKLAlDLmNpaXAKLAlVLnVzZXIKLAlkdGV2ZW50CiwJTS5tZXRob2QKLAlMLmxwYXRoCiwJUC5scGFnZQosCUEuYXJncwosCXJjCiwJcnN6CiwJaXN6CiwJb3N6CglGUk9NIFRfRXZlbnRzIEFTIEUKCUlOTkVSIEpPSU4gVmhvc3RzICAgIEFTIFYgT04gKFYuaWQ9PUUuaWRfdmhvc3QpCglJTk5FUiBKT0lOIEhob3N0cyAgICBBUyBIIE9OIChILmlkPT1FLmlkX2hob3N0KQoJSU5ORVIgSk9JTiBDbGllbnRzICAgQVMgQyBPTiAoQy5pZD09RS5pZF9jbGllbnQpCglJTk5FUiBKT0lOIFVzZXJzICAgICBBUyBVIE9OIChVLmlkPT1FLmlkX3VzZXIpCglJTk5FUiBKT0lOIE1ldGhvZHMgICBBUyBNIE9OIChNLmlkPT1FLmlkX21ldGhvZCkKCUlOTkVSIEpPSU4gTHBhdGhzICAgIEFTIEwgT04gKEwuaWQ9PUUuaWRfbHBhdGgpCglJTk5FUiBKT0lOIExwYWdlcyAgICBBUyBQIE9OIChQLmlkPT1FLmlkX2xwYWdlKQoJSU5ORVIgSk9JTiBBcmdzcyAgICAgQVMgQSBPTiAoQS5pZD09RS5pZF9hcmdzKTsKCi0tICAgIFRoZSB0cmlnZ2VyIHRoYXQgZGVmZXJzIHRoZSBpbnNlcnQgaW50byB2aWV3IHRvIGluc2VydCBpbiBldmVudHMsIHdpdGggYWxsIHBvaW50ZXJzIGxvb2tlZCB1cCBhbmQgZmlsbGVkIGluLgpDUkVBVEUgVFJJR0dFUiBpb19pbnNfTG9nbGluZXMgSU5TVEVBRCBPRiBJTlNFUlQgT04gTG9nbGluZXMKRk9SIEVBQ0ggUk9XCkJFR0lOCglJTlNFUlQgSU5UTyBUX0V2ZW50cyAoCglpZF9sb2cKLAlsaW5lbnIKLAlpZF92aG9zdAosCWlkX2hob3N0CiwJaWRfY2xpZW50CiwJaWRfdXNlcgosCWR0ZXZlbnQKLAlpZF9tZXRob2QKLAlpZF9scGF0aAosCWlkX2xwYWdlCiwJaWRfYXJncwosCXJjCiwJcnN6CiwJaXN6CiwJb3N6KSBWQUxVRVMgKAoJTkVXLmlkX2xvZwosCU5FVy5saW5lbnIKLAkoU0VMRUNUIGlkIEZST00gVmhvc3RzICBXSEVSRSAgdmhvc3Q9PU5FVy52aG9zdCkKLAkoU0VMRUNUIGlkIEZST00gSGhvc3RzICBXSEVSRSAgaGhvc3Q9PU5FVy5oaG9zdCkKLAkoU0VMRUNUIGlkIEZST00gQ2xpZW50cyBXSEVSRSBjbGllbnQ9PU5FVy5jbGllbnQpCiwJKFNFTEVDVCBpZCBGUk9NIFVzZXJzICAgV0hFUkUgICB1c2VyPT1ORVcudXNlcikKLAlORVcuZHRldmVudAosCShTRUxFQ1QgaWQgRlJPTSBNZXRob2RzIFdIRVJFIG1ldGhvZD09TkVXLm1ldGhvZCkKLAkoU0VMRUNUIGlkIEZST00gTHBhdGhzICBXSEVSRSAgbHBhdGg9PU5FVy5scGF0aCkKLAkoU0VMRUNUIGlkIEZST00gTHBhZ2VzICBXSEVSRSAgbHBhZ2U9PU5FVy5scGFnZSkKLAkoU0VMRUNUIGlkIEZST00gQXJnc3MgICBXSEVSRSAgIGFyZ3M9PU5FVy5hcmdzKQosCU5FVy5yYwosCU5FVy5yc3oKLAlORVcuaXN6CiwJTkVXLm9zeik7CkVORDsKCi0tIFRyaWdnZXJzIGZvciB1cGRhdGluZyByZWZlcmVuY2UgY291bnRlcnMKLS0gc3BlZWRzIHVwIHJlcG9ydGluZywgc2xvd3MgZG93biB1cGRhdGVzCgpDUkVBVEUgVFJJR0dFUiBhX2luc19ldmVudHMgQUZURVIgSU5TRVJUIE9OIFRfRXZlbnRzCkZPUiBFQUNIIFJPVwpCRUdJTgoJVVBEQVRFIExvZ3MgICAgU0VUIHJlZmNudCA9IHJlZmNudCArIDEgV0hFUkUgaWQgPSBORVcuaWRfbG9nOwoJVVBEQVRFIFZob3N0cyAgU0VUIHJlZmNudCA9IHJlZmNudCArIDEgV0hFUkUgaWQgPSBORVcuaWRfdmhvc3Q7CglVUERBVEUgSGhvc3RzICBTRVQgcmVmY250ID0gcmVmY250ICsgMSBXSEVSRSBpZCA9IE5FVy5pZF9oaG9zdDsKCVVQREFURSBDbGllbnRzIFNFVCByZWZjbnQgPSByZWZjbnQgKyAxIFdIRVJFIGlkID0gTkVXLmlkX2NsaWVudDsKCVVQREFURSBVc2VycyAgIFNFVCByZWZjbnQgPSByZWZjbnQgKyAxIFdIRVJFIGlkID0gTkVXLmlkX3VzZXI7CglVUERBVEUgTWV0aG9kcyBTRVQgcmVmY250ID0gcmVmY250ICsgMSBXSEVSRSBpZCA9IE5FVy5pZF9tZXRob2Q7CglVUERBVEUgTHBhdGhzICBTRVQgcmVmY250ID0gcmVmY250ICsgMSBXSEVSRSBpZCA9IE5FVy5pZF9scGF0aDsKCVVQREFURSBMcGFnZXMgIFNFVCByZWZjbnQgPSByZWZjbnQgKyAxIFdIRVJFIGlkID0gTkVXLmlkX2xwYWdlOwoJVVBEQVRFIEFyZ3NzICAgU0VUIHJlZmNudCA9IHJlZmNudCArIDEgV0hFUkUgaWQgPSBORVcuaWRfYXJnczsKRU5EOwoKQ1JFQVRFIFRSSUdHRVIgYV9kZWxfZXZlbnRzIEFGVEVSIERFTEVURSBPTiBUX0V2ZW50cwpGT1IgRUFDSCBST1cKQkVHSU4KCVVQREFURSBMb2dzICAgIFNFVCByZWZjbnQgPSByZWZjbnQgLSAxIFdIRVJFIGlkID0gT0xELmlkX2xvZzsKCVVQREFURSBWaG9zdHMgIFNFVCByZWZjbnQgPSByZWZjbnQgLSAxIFdIRVJFIGlkID0gT0xELmlkX3Zob3N0OwoJVVBEQVRFIEhob3N0cyAgU0VUIHJlZmNudCA9IHJlZmNudCAtIDEgV0hFUkUgaWQgPSBPTEQuaWRfaGhvc3Q7CglVUERBVEUgQ2xpZW50cyBTRVQgcmVmY250ID0gcmVmY250IC0gMSBXSEVSRSBpZCA9IE9MRC5pZF9jbGllbnQ7CglVUERBVEUgVXNlcnMgICBTRVQgcmVmY250ID0gcmVmY250IC0gMSBXSEVSRSBpZCA9IE9MRC5pZF91c2VyOwoJVVBEQVRFIE1ldGhvZHMgU0VUIHJlZmNudCA9IHJlZmNudCAtIDEgV0hFUkUgaWQgPSBPTEQuaWRfbWV0aG9kOwoJVVBEQVRFIExwYXRocyAgU0VUIHJlZmNudCA9IHJlZmNudCAtIDEgV0hFUkUgaWQgPSBPTEQuaWRfbHBhdGg7CglVUERBVEUgTHBhZ2VzICBTRVQgcmVmY250ID0gcmVmY250IC0gMSBXSEVSRSBpZCA9IE9MRC5pZF9scGFnZTsKCVVQREFURSBBcmdzcyAgIFNFVCByZWZjbnQgPSByZWZjbnQgLSAxIFdIRVJFIGlkID0gT0xELmlkX2FyZ3M7CkVORDsKCkNSRUFURSBWSUVXIEFiYnJldmxvZ2xpbmVzIEFTIAogIFNFTEVDVCAKCUUuaWQKLAlpZF9sb2cKLAlsaW5lbnIKLAlWLnZoCiwJSC5oaAosCUguaGhvc3QKLAlDLmNsaWVudAosCVUudXNlcgosCWR0ZXZlbnQKLAlNLm1ldGhvZAosCUwubHBhdGgKLAlyYwosCXJzegosCWlzegosCW9zegoJRlJPTSBUX0V2ZW50cyBBUyBFCglJTk5FUiBKT0lOIFZob3N0cyAgICBBUyBWIE9OIChWLmlkPT1FLmlkX3Zob3N0KQoJSU5ORVIgSk9JTiBIaG9zdHMgICAgQVMgSCBPTiAoSC5pZD09RS5pZF9oaG9zdCkKCUlOTkVSIEpPSU4gQ2xpZW50cyAgIEFTIEMgT04gKEMuaWQ9PUUuaWRfY2xpZW50KQoJSU5ORVIgSk9JTiBVc2VycyAgICAgQVMgVSBPTiAoVS5pZD09RS5pZF91c2VyKQoJSU5ORVIgSk9JTiBNZXRob2RzICAgQVMgTSBPTiAoTS5pZD09RS5pZF9tZXRob2QpCglJTk5FUiBKT0lOIExwYXRocyAgICBBUyBMIE9OIChMLmlkPT1FLmlkX2xwYXRoKTsKCi0tIFNlY3Rpb24gNC4gQW55IG90aGVyIHRhYmxlcwotLSAgICBEYXRlcywgY2FuIGJlIHVzZWQgYXMgSW50ZWdlcnMgYXMgd2VsbApDUkVBVEUgVEFCTEUgRGF0ZXMgKAoJaWQgSU5URUdFUiBQUklNQVJZIEtFWSAgTk9UIE5VTEwKLAlkICAgICAgICAgIFJFQUwKKTsKCkNSRUFURSBUQUJMRSBLbm93bklQcyAoCglpcGRvdHRlZCAgIFRFWFQgUFJJTUFSWSBLRVkgTk9UIE5VTEwKLAlvd25lciAgICAgIFRFWFQgREVGQVVMVCAna251eXQnCiwJaWRfY2F0ICAgICBJTlRFR0VSIE5PVCBOVUxMIERFRkFVTFQgMCBSRUZFUkVOQ0VTIENhdGVnb3JpZXMgKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSBPTiBVUERBVEUgQ0FTQ0FERQopOwoKLS0gRU9G