├── .gitignore ├── .index.html ├── JavaScript ├── Calendar.js ├── Contents.js ├── ContentsMain.js ├── CustomEditor.js ├── DatabaseView.js ├── FileView.js ├── Log.js ├── Main.js ├── PluginView.js ├── Session.js ├── SettingView.js ├── TextEditor.js ├── UserView.js └── include │ ├── AflLib.js │ ├── Gui.js │ └── md5.js ├── PHP ├── LocalDB.php ├── MainDB.php ├── Manager.php ├── Modules │ ├── Calendar.php │ ├── Contents.php │ ├── Files.php │ ├── GParams.php │ ├── Log.php │ ├── Params.php │ ├── Session.php │ └── Users.php └── include │ ├── Database.php │ ├── PostgreSQL.php │ └── SQLite.php ├── css ├── Gui.css ├── Main.css ├── TextEditor.css ├── images │ ├── close.svg │ ├── file.svg │ ├── folder.svg │ ├── max.svg │ ├── min.svg │ ├── normal.svg │ ├── talone.svg │ ├── tclose.svg │ └── topen.svg └── routeros.css ├── index.php └── save └── readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | .vscode 3 | save/.local.db 4 | robots.txt 5 | favicon.ico 6 | test.html 7 | -------------------------------------------------------------------------------- /.index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | [[SCRIPTS]] 9 | [[TITLE]] 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /JavaScript/Calendar.js: -------------------------------------------------------------------------------- 1 | function createCalendar(parent) { 2 | var view = createCalendarView(); 3 | view.changeFrameWindow(); 4 | view.setSize(400, 300); 5 | return view; 6 | } 7 | function createHolidayCanendar(parent) { 8 | var window = createCalendar(parent); 9 | function onClick(e) { 10 | var cell = e.currentTarget; 11 | var text = cell.childNodes[1]; 12 | var rect = text.getBoundingClientRect(); 13 | var edit = GUI.createEditView(); 14 | 15 | 16 | edit.setText(text.innerText); 17 | edit.setSize(rect.width, rect.height); 18 | edit.setPos(rect.left, rect.top); 19 | edit.setOrderSystem(true); 20 | edit.setFocus(); 21 | edit.addEvent("enter", function (e) { 22 | var values = { 23 | "command": "setHoliday", "sessionHash": sessionStorage.getItem("sessionHash"), 24 | "date": cell.date.toLocaleString(), "name": e.value 25 | }; 26 | AFL.sendJson(SCRIPT_URL, values, function (r) { 27 | if (r != null && r.result) { 28 | text.innerText = e.value; 29 | cell.id = e.value == "" ? "" : "Holiday"; 30 | } 31 | }); 32 | }); 33 | } 34 | window.getCalendar().addEvent("clickDay", onClick); 35 | } 36 | function createCalendarView() { 37 | var week = "日月火水木金土"; 38 | var window = GUI.createWindow(); 39 | window.GUI.date = new Date(); 40 | var client = window.getClient(); 41 | client.className = "GUICalendar"; 42 | 43 | var table = document.createElement("table"); 44 | client.appendChild(table); 45 | var titleLine = table.insertRow(-1); 46 | titleLine.className = "TitleLine"; 47 | var prev = titleLine.insertCell(-1); 48 | prev.className = "Button"; 49 | prev.innerText = "⇐"; 50 | prev.addEventListener("click", prevMonth); 51 | var titleText = titleLine.insertCell(-1); 52 | titleText.colSpan = 5; 53 | titleText.className = "TitleText"; 54 | 55 | var next = titleLine.insertCell(-1); 56 | next.innerText = "⇒"; 57 | next.className = "Button"; 58 | next.addEventListener("click", nextMonth); 59 | 60 | var cells = {}; 61 | for (var j = 0; j < 7; j++) { 62 | var line = table.insertRow(-1); 63 | line.className = "Line"; 64 | 65 | for (var i = 0; i < 7; i++) { 66 | var cell = line.insertCell(-1); 67 | cell.className = "Cell"; 68 | cell.addEventListener("click", function (e) { 69 | var d = this.date.toLocaleDateString(); 70 | if (window.GUI.eventDate && window.GUI.eventDate[d] != null) 71 | e.value = window.GUI.eventDate[d]; 72 | e.etype = "clickDay"; 73 | e.date = this.date; 74 | window.callEvent(e); 75 | }); 76 | if (j == 0) 77 | cell.innerHTML = week.substr(i, 1); 78 | else { 79 | var cellBody = document.createElement("div"); 80 | cellBody.className = "CellBody"; 81 | cell.appendChild(cellBody); 82 | 83 | var day = document.createElement("div"); 84 | day.className = "Day"; 85 | cellBody.appendChild(day); 86 | var dayText = document.createElement("div"); 87 | dayText.className = "DayText"; 88 | cellBody.appendChild(dayText); 89 | 90 | 91 | } 92 | } 93 | } 94 | function nextMonth() { 95 | var date = window.GUI.date; 96 | window.setDate(new Date(date.getFullYear(), date.getMonth() + 1)); 97 | } 98 | function prevMonth() { 99 | var date = window.GUI.date; 100 | window.setDate(new Date(date.getFullYear(), date.getMonth() - 1)); 101 | } 102 | 103 | function getHoliday(dateStart) { 104 | var dateEnd = new Date(dateStart.getTime()); 105 | dateEnd.setDate(dateEnd.getDate() + 42); 106 | ADP.exec("Calendar.getHoliday", dateStart, dateEnd).on = function (value) { 107 | if (value) { 108 | for (var i = 0; i < value.length; i++) { 109 | var value = value[i]; 110 | var d = value[0].split('-').join('/');; 111 | var date = new Date(d); 112 | var cell = cells[date]; 113 | if (cell) { 114 | cell.id = "Holiday" 115 | cell.childNodes[0].childNodes[1].innerText = value[1]; 116 | } 117 | } 118 | } 119 | } 120 | } 121 | var mHolidays = {}; 122 | function getHoliday(dateStart) { 123 | function drawHoliday(holidays) { 124 | for (var i = 0; i < holidays.length; i++) { 125 | var value = holidays[i]; 126 | var d = value[0].split('-').join('/');; 127 | var date = new Date(d); 128 | var cell = cells[date]; 129 | if (cell) { 130 | cell.id = "Holiday" 131 | cell.childNodes[0].childNodes[1].textContent = value[1]; 132 | } 133 | } 134 | } 135 | 136 | var dateEnd = new Date(dateStart.getTime()); 137 | dateEnd.setDate(dateEnd.getDate() + 42); 138 | var d = dateStart.toLocaleDateString() + dateEnd.toLocaleDateString(); 139 | if (mHolidays[d] != null) { 140 | drawHoliday(mHolidays[d]); 141 | return; 142 | } 143 | 144 | ADP.exec("Calendar.getHoliday", dateStart, dateEnd).on = function (value) { 145 | if (value) { 146 | mHolidays[d] = value; 147 | drawHoliday(value); 148 | } 149 | }; 150 | } 151 | 152 | window.redraw = function () { 153 | var now = new Date(); 154 | var date = new Date(this.GUI.date.getFullYear(), this.GUI.date.getMonth(), 1); 155 | table.rows[0].cells[1].innerText = AFL.sprintf("%d年%d月", date.getFullYear(), date.getMonth() + 1); 156 | 157 | date.setDate(date.getDate() - date.getDay()); 158 | var dateStart = new Date(date.getTime()); 159 | this.GUI.start = dateStart; 160 | this.GUI.end = new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate() + 42); 161 | 162 | cells = {}; 163 | for (var j = 2; j < 8; j++) { 164 | for (var i = 0; i < 7; i++) { 165 | var d = new Date(date.getTime()); 166 | var cell = table.rows[j].cells[i]; 167 | cells[d] = cell; 168 | cell.date = d; 169 | cell.id = ""; 170 | cell.childNodes[0].id = now.toLocaleDateString() == date.toLocaleDateString() ? "now" : ""; 171 | cell.childNodes[0].childNodes[0].innerText = date.getDate(); 172 | cell.childNodes[0].childNodes[1].innerText = ""; 173 | 174 | if (this.GUI.eventDate != null && this.GUI.eventDate[date.toLocaleDateString()] != null) 175 | cell.classList.add("Event"); 176 | else 177 | cell.classList.remove("Event"); 178 | date.setDate(date.getDate() + 1); 179 | } 180 | } 181 | getHoliday(dateStart); 182 | } 183 | window.setEventDate = function (dates) { 184 | this.GUI.eventDate = dates; 185 | } 186 | window.setDate = function (date, flag) { 187 | this.GUI.date = new Date(date.getTime()); 188 | this.redraw(); 189 | var e = {}; 190 | e.etype = "changeDate"; 191 | e.date = this.GUI.date; 192 | e.start = this.GUI.start; 193 | e.end = this.GUI.end; 194 | e.redraw = flag == null ? true : flag; 195 | window.callEvent(e); 196 | } 197 | window.getDate = function () { 198 | return this.GUI.date; 199 | } 200 | window.redraw(); 201 | return window; 202 | } 203 | 204 | function importHoliday() { 205 | var win = GUI.createWindow(); 206 | win.setTitle("祝日のインポート(内閣府データ)"); 207 | win.setSize(400, 200); 208 | win.setPos(); 209 | 210 | var client = win.getClient(); 211 | client.className = "IMPORT_CALENDAR"; 212 | client.innerHTML = ""; 213 | var button = client.querySelector("button"); 214 | button.addEventListener("click", function () { 215 | ADP.exec("Calendar.importHoliday").on = function (value) { 216 | if (value) { 217 | client.innerHTML = "正常終了"; 218 | } else 219 | client.innerHTML = "異常終了"; 220 | } 221 | }); 222 | return win; 223 | } -------------------------------------------------------------------------------- /JavaScript/Contents.js: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | //URLのパラメータ部分から、表示ページを切り替え 3 | function goLocation() { 4 | //パラメータの読み出し 5 | var p = {}; 6 | location.search.substring(1).split('&').forEach(function (v) { s = v.split('='); p[s[0]] = s[1]; }); 7 | //指定ページに飛ぶ 8 | Contents.selectContents(p['p'] >= 1 ? p['p'] : 1, false); 9 | } 10 | 11 | //ブラウザの「戻る」「進む」ボタンが押された場合のイベント処理 12 | addEventListener('popstate', function () { goLocation(); }, false); 13 | 14 | Contents = {events:{},editors:[],nodes:[],visible:true}; 15 | GUI.createEvent(Contents); 16 | 17 | Contents.addEditor = function(editor){ 18 | this.editors.push(editor); 19 | } 20 | Contents.delEditor = function(editor){ 21 | var index = this.editors.indexOf(editor); 22 | if (index >= 0) 23 | this.editors.splice(index, 1); 24 | } 25 | Contents.createContents = function(pid,vector,type){ 26 | ADP.exec("Contents.createContents",pid,vector,type).on = function(value){ 27 | if (value){ 28 | Contents.callEvent({etype:"create",value:value}); 29 | } 30 | } 31 | } 32 | Contents.loadTitle = function(){ 33 | ADP.exec("Params.getParam", "base_title").on = function (value) { 34 | System.title = value; 35 | Contents.callEvent({etype:"title",title:value}); 36 | } 37 | } 38 | Contents.createContentsMenu = function(id,type,node){ 39 | var menu = createMenu(["兄弟(↑)", "兄弟(↓)", "子(↑)", "子(↓)"],node); 40 | menu.addEvent("select", function (e) { 41 | Contents.createContents(id, e.value, type); 42 | }); 43 | } 44 | Contents.createContentsMenu2 = function (id, node) { 45 | var menu = createMenu(["Visible","Export","Import"], node); 46 | menu.addEvent("select", function (e) { 47 | switch (parseInt(e.value)){ 48 | case 1: 49 | window.open(AFL.sprintf("?command=Contents.export&id=%d&sessionHash=%s", id, ADP.sessionHash)); 50 | break; 51 | case 2: 52 | createImportView(id); 53 | break; 54 | } 55 | }); 56 | } 57 | Contents.updateContents = function(value){ 58 | Contents.callEvent({ etype: "update", value:value}); 59 | } 60 | Contents.isVisible = function () { 61 | return Contents.visible; 62 | } 63 | Contents.setVisible = function (flag) { 64 | Contents.visible = flag; 65 | Contents.nodes = []; 66 | Contents.loadTree(); 67 | document.body.dataset.visible = flag; 68 | } 69 | Contents.loadTree = function () { 70 | Contents.nodes = []; 71 | ADP.exec("Contents.getTree").on = function (value) { 72 | if (value) { 73 | Contents.callEvent({etype:"loadTree",value:value}); 74 | } 75 | } 76 | } 77 | Contents.moveVector = function (id, vector) { 78 | ADP.exec("Contents.moveVector", id, vector).on = function (flag) { 79 | if (flag) { 80 | Contents.callEvent({ etype: "vector", id: id,vector:vector }); 81 | } 82 | } 83 | } 84 | Contents.moveContents = function(fromId,toId){ 85 | ADP.exec("Contents.moveContents", fromId, toId).on = function (flag) { 86 | if (flag) { 87 | Contents.loadTree(); 88 | } 89 | } 90 | } 91 | 92 | Contents.selectContents = function (id) { 93 | Contents.callEvent({etype:"select",id:id}); 94 | } 95 | Contents.deleteContents = function (id) { 96 | ADP.exec("Contents.deleteContents", id).on = function (ids) { 97 | Contents.callEvent({etype:"delete",ids:ids}); 98 | } 99 | } 100 | 101 | function createBreadcrumb(item){ 102 | if(!item) 103 | return; 104 | var url = location.href.replace(/\?.*$/,""); 105 | var list = []; 106 | do{ 107 | var bradcrumb = { 108 | "@type": "ListItem", 109 | "position": 1, 110 | "item": 111 | { 112 | "@id": url+"?p="+item.getItemValue(), 113 | "name": item.getItemText() 114 | } 115 | } 116 | list.unshift(bradcrumb); 117 | }while(item = item.getParentItem()); 118 | for(var i=0;i 0 || ua.indexOf('iPad') > 0 || ua.indexOf('Android') > 0) 155 | separate.setOverlay(true); 156 | 157 | var contentsMain = createContentsView(); 158 | separate.addSeparateChild(1, contentsMain, "client"); 159 | 160 | //広告領域 161 | // var adArea = GUI.createWindow(); 162 | // adArea.setHeight(300); 163 | // separate.addSeparateChild(0, adArea, "bottom"); 164 | // System.adArea = adArea; 165 | 166 | var treeView = GUI.createTreeView(); 167 | separate.getChild(0).getClient().style.backgroundColor = 'transparent'; 168 | treeView.getClient().style.backgroundColor = 'rgba(255,255,255,0.8)'; 169 | separate.addSeparateChild(0,treeView,"client"); 170 | treeView.addEvent("select", function (r) { 171 | var id = treeView.getSelectValue(); 172 | 173 | var p = {}; 174 | location.search.substring(1).split('&').forEach(function (v) { s = v.split('='); p[s[0]] = s[1]; }); 175 | var p = p["p"] ? p["p"]:1; 176 | if(p != id){ 177 | //URLの書き換え 178 | history.pushState(null, null, "?p=" + id); 179 | 180 | } 181 | 182 | if (System.baseUrl) { 183 | var canonical = document.querySelector('link[rel=canonical]'); 184 | if (!canonical) { 185 | canonical = document.createElement('link'); 186 | canonical.rel = 'canonical'; 187 | document.head.appendChild(canonical); 188 | } 189 | canonical.href = System.baseUrl + '?p=' + id; 190 | } 191 | 192 | var item = treeView.getSelectItem(); 193 | if(!item) 194 | item = treeView.getRootItem(); 195 | //パンくずリスト生成 196 | createBreadcrumb(item); 197 | //親アイテムも含めて展開 198 | do{ 199 | item.openItem(true); 200 | }while(item = item.getParentItem()); 201 | 202 | 203 | //タイトル設定 204 | item = treeView.getSelectItem(); 205 | var title = item.getItemText(); 206 | while (item = item.getParentItem()) { 207 | title += " ~ " + item.getItemText(); 208 | } 209 | document.title = title + " ~ " + System.title; 210 | //コンテンツの読み出し 211 | contentsMain.loadContents(id); 212 | }); 213 | 214 | 215 | //管理者用編集メニュー 216 | if (SESSION.isAuthority("SYSTEM_ADMIN")){ 217 | var mOptionNode = document.createElement("div"); 218 | mOptionNode.innerHTML = "🖊🔧🔺🔻"; 219 | mOptionNode.className = "TreeOption"; 220 | var options = mOptionNode.querySelectorAll("span"); 221 | for(var i=0;i 0) { 278 | for(var i in ids){ 279 | var id = ids[i]; 280 | //ツリー削除処理 281 | var item = treeView.findItem(id); 282 | if(item) 283 | item.delItem(); 284 | } 285 | 286 | //Editorクローズ処理 287 | for (var i = Contents.editors.length - 1; i >= 0; i--) { 288 | var editor = Contents.editors[i]; 289 | if (ids.indexOf(editor.getId()) >= 0) 290 | editor.close(); 291 | } 292 | var contents = Contents.nodes[id]; 293 | if (contents) { 294 | contents.deleteContents(); 295 | } 296 | } 297 | }); 298 | Contents.addEvent("create", function (r) { 299 | var value = r.value; 300 | treeView.reloadTree(value.pid, value.id); 301 | }); 302 | 303 | Contents.addEvent("select",function(r){ 304 | var item = treeView.findItem(r.id); 305 | if (item) { 306 | item.select(); 307 | item.openItem(true); 308 | 309 | } 310 | }); 311 | Contents.addEvent("update", function (r) { 312 | var value = r.value; 313 | var item = treeView.findItem(value["id"]); 314 | if (item) { 315 | if (item.dataset.type != value["type"]) { 316 | treeView.reloadTree(item.getParentItem().getItemValue(), value["id"]); 317 | }else{ 318 | item.setItemText(value["title"]); 319 | item.dataset.stat = value["stat"]; 320 | item.dataset.visible = "true"; 321 | } 322 | } 323 | }); 324 | Contents.addEvent("loadTree", function (r) { 325 | treeView.clearItem(); 326 | setTreeItem(treeView.getRootItem(), r.value); 327 | goLocation(); 328 | }); 329 | treeView.loadTree = function(){ 330 | Contents.nodes = []; 331 | ADP.exec("Contents.getTree").on = function(value){ 332 | if (value){ 333 | treeView.clearItem(); 334 | setTreeItem(treeView.getRootItem(), value); 335 | } 336 | goLocation(); 337 | } 338 | } 339 | treeView.reloadTree = function (id, sid) { 340 | Contents.nodes = []; 341 | ADP.exec("Contents.getTree", id).on = function (value) { 342 | var item = treeView.findItem(id); 343 | item.clearItem(); 344 | setTreeItem(item, value); 345 | if (sid !== null) { 346 | Contents.selectContents(sid); 347 | } 348 | } 349 | } 350 | 351 | Contents.loadTree(); 352 | return separate; 353 | } 354 | function createImportView(id){ 355 | function onDropFile(e){ 356 | e.preventDefault(); 357 | var file = e.dataTransfer.files[0]; 358 | var value = file.lastModifiedDate.toLocaleDateString(); 359 | var reader = new FileReader(); 360 | reader.readAsText(file); 361 | reader.onload = function () { 362 | var mode = client.querySelector("input"); 363 | ADP.exec("Contents.import", id, mode.checked?0:1,this.result).on = function(){ 364 | Contents.loadTree(); 365 | win.close(); 366 | }; 367 | } 368 | } 369 | 370 | var win = GUI.createFrameWindow(); 371 | win.setTitle("インポート"); 372 | win.setSize(300,200); 373 | win.setPos(); 374 | var client = win.getClient(); 375 | client.innerHTML = 376 | "
"+ 377 | "
ファイルをドロップすると開始

"+ 378 | "
"+ 379 | "
"; 380 | 381 | client.addEventListener("drop", onDropFile); 382 | client.ondragover = function (e) { 383 | e.preventDefault(); 384 | } 385 | return win; 386 | } -------------------------------------------------------------------------------- /JavaScript/ContentsMain.js: -------------------------------------------------------------------------------- 1 | 2 | function scrollTo(node,pos){ 3 | if(this.handle) 4 | clearInterval(this.handle); 5 | pos -= 20; 6 | if(pos < 0) 7 | pos = 0; 8 | var limit = node.scrollHeight -node.clientHeight; 9 | if (pos > limit) 10 | pos = limit; 11 | this.handle = setInterval(function(){ 12 | var p = pos - node.scrollTop; 13 | if(Math.abs(p) < 5){ 14 | node.scrollTop = pos; 15 | clearInterval(this.handle); 16 | this.handle = null; 17 | } 18 | else 19 | node.scrollTop += p/5; 20 | 21 | },10); 22 | } 23 | 24 | //outputAd(広告を挿入するノード,広告コード) 25 | function outputAd(node, code,flag) { 26 | //document.writeのフック 27 | if (flag){ 28 | var documentWrite = document.write; 29 | document.write = function (value) { 30 | var t = this; 31 | node.innerHTML = value; 32 | document.write = documentWrite; 33 | } 34 | } 35 | //ノード内のデータを削除 36 | while (node.childNodes.length) 37 | node.removeChild(node.childNodes[0]) 38 | //広告コードをダミーノードに設定 39 | var dummy = document.createElement('div'); 40 | dummy.innerHTML = code; 41 | while (dummy.childNodes.length) { 42 | var child = dummy.childNodes[0]; 43 | dummy.removeChild(child); 44 | if (child.nodeName === 'SCRIPT') { 45 | //スクリプトなら再生成 46 | var script = document.createElement('SCRIPT'); 47 | if (child.src) 48 | script.src = child.src; 49 | script.async = child.async; 50 | script.innerHTML = child.innerHTML; 51 | 52 | node.appendChild(script); 53 | } 54 | else 55 | node.appendChild(child); 56 | } 57 | } 58 | function createAdsenseNode(parent,pos){ 59 | var code; 60 | if (!System.adsense) 61 | return; 62 | if(pos == 'TOP'){ 63 | code = System.adsense.top; 64 | } 65 | if (pos == 'BOTTOM') { 66 | code = System.adsense.bottom; 67 | } 68 | if (pos == 'INNER') { 69 | code = System.adsense.inner; 70 | } 71 | if(!code) 72 | return null; 73 | 74 | var adArea = document.createElement('div'); 75 | if (pos == 'TOP') 76 | parent.insertBefore(adArea, parent.firstChild); 77 | else 78 | parent.appendChild(adArea); 79 | outputAd(adArea,code); 80 | setTimeout(function(){ 81 | try { 82 | (adsbygoogle = window.adsbygoogle || []).push({}); 83 | } catch (e) { } 84 | },10); 85 | } 86 | function createAdsenseNode2(parent, pos) { 87 | var code; 88 | if (!System.rakuten) 89 | return null; 90 | if (pos == 'TOP') { 91 | code = System.rakuten.top; 92 | } 93 | if (pos == 'BOTTOM') { 94 | code = System.rakuten.bottom; 95 | } 96 | if (pos == 'INNER') { 97 | code = System.rakuten.inner; 98 | } 99 | if (!code) 100 | return null; 101 | 102 | var adArea = document.createElement('div'); 103 | if (pos == 'TOP') 104 | parent.insertBefore(adArea, parent.firstChild); 105 | else 106 | parent.appendChild(adArea); 107 | outputAd(adArea, code, true); 108 | } 109 | function createAdsenseNode3(parent, pos) { 110 | var code; 111 | if (!System.amazon) 112 | return null; 113 | if (pos == 'TOP') { 114 | code = System.amazon.top; 115 | } 116 | if (pos == 'BOTTOM') { 117 | code = System.amazon.bottom; 118 | } 119 | if (pos == 'SIDE') { 120 | code = System.amazon.side; 121 | } 122 | if (!code) 123 | return null; 124 | 125 | var adArea = document.createElement('div'); 126 | if (pos == 'TOP') 127 | parent.insertBefore(adArea, parent.firstChild); 128 | else 129 | parent.appendChild(adArea); 130 | outputAd(adArea, code,true); 131 | 132 | 133 | } 134 | function createContentsView(){ 135 | function jumpContents(id) { 136 | if (Contents.nodes[id]) { 137 | node = Contents.nodes[id]; 138 | var y = node.getBoundingClientRect().top - page.getBoundingClientRect().top; 139 | setTimeout(function(){scrollTo(client, y-200);},0); 140 | } 141 | } 142 | 143 | var win = GUI.createWindow(); 144 | var client = win.getClient(); 145 | client.style = "overflow:auto;"; 146 | var page = document.createElement("div"); 147 | page.className = "ContentsPage"; 148 | client.appendChild(page); 149 | win.loadContents = function(id){ 150 | //コンテンツが存在するなら移動して終了 151 | if (Contents.nodes[id]){ 152 | jumpContents(id); 153 | return; 154 | } 155 | 156 | ADP.exec("Contents.getContentsPage",id).on=function(value){ 157 | win.removeChildAll(); 158 | if(value === null) 159 | return; 160 | 161 | Contents.nodes = []; 162 | while (page.childNodes.length) 163 | page.removeChild(page.childNodes[0]); 164 | var contents = createContents(value); 165 | page.appendChild(contents); 166 | 167 | var contentsChilds = contents.querySelectorAll('.ContentsArea'); 168 | 169 | var allHeight = 0; 170 | var height = 0; 171 | //記事内広告の設定 172 | for(var i=0;i 1000 && i !== contentsChilds.length-1){ 175 | //createAdsenseNode(c, "INNER"); 176 | height = 0; 177 | } 178 | height += c.offsetHeight; 179 | allHeight += c.offsetHeight; 180 | } 181 | 182 | 183 | if(allHeight > 300) 184 | createAdsenseNode(page,"TOP"); //トップ広告の挿入 185 | 186 | if (height > 1000) 187 | createAdsenseNode(page, "BOTTOM"); //ボトム広告の挿入 188 | 189 | //サイドバー 190 | // var client = System.adArea.getClient() 191 | // // while (client.childNodes.length) 192 | // // client.removeChild(client.childNodes[0]) 193 | // if (client.childNodes.length === 0) 194 | // createAdsenseNode3(System.adArea.getClient(),"SIDE"); 195 | 196 | jumpContents(id); 197 | 198 | //トラッカーに通知 199 | try { 200 | gtag('config', AnalyticsUA, { 'page_title': value["title"], 'page_path': '/?p=' + value["id"]}); 201 | } catch (e) { } 202 | 203 | var desc = document.head.querySelector("meta[name=description]"); 204 | if(!desc){ 205 | desc = document.createElement("meta"); 206 | desc.name = "description"; 207 | document.head.appendChild(desc); 208 | } 209 | desc.content = page.querySelector(".Body").textContent.substr(0,40); 210 | 211 | } 212 | } 213 | win.moveVector = function (id, vector){ 214 | var node = Contents.nodes[id]; 215 | if(node == null) 216 | return; 217 | var parent = node.parentNode; 218 | var childs = parent.childNodes; 219 | for (var i = 0; i < childs.length; i++) { 220 | if (childs[i] === node) { 221 | if (vector < 0) { 222 | if (i === 0) 223 | return false; 224 | parent.insertBefore(node, childs[i - 1]); 225 | } else { 226 | if (i === childs.length - 1) 227 | return false; 228 | parent.insertBefore(childs[i + 1], node); 229 | } 230 | break; 231 | } 232 | } 233 | } 234 | Contents.addEvent("update",function(r){ 235 | var value = r.value; 236 | var contents = Contents.nodes[value["id"]]; 237 | if (contents) 238 | contents.updateContents(value); 239 | }); 240 | Contents.addEvent("delete", function (r) { 241 | var ids = r.ids; 242 | if (ids && ids.length > 0) { 243 | for (var i in ids) { 244 | var id = ids[i]; 245 | var contents = Contents.nodes[id]; 246 | if (contents) { 247 | contents.deleteContents(); 248 | } 249 | } 250 | } 251 | }); 252 | return win; 253 | } 254 | function createContents(value){ 255 | var area = document.createElement('div'); 256 | area.className = "ContentsArea"; 257 | Contents.nodes[value["id"]] = area; 258 | var contents = document.createElement('div'); 259 | contents.className = "Contents"; 260 | area.appendChild(contents); 261 | 262 | //管理者用編集メニュー 263 | if (SESSION.isAuthority("SYSTEM_ADMIN")) 264 | contents.appendChild(createControlPanel(value["id"])); 265 | 266 | var title = document.createElement('div'); 267 | contents.appendChild(title); 268 | 269 | var date = document.createElement('div'); 270 | date.className = "Date"; 271 | contents.appendChild(date); 272 | 273 | var body = document.createElement('div'); 274 | body.className = "Body"; 275 | contents.appendChild(body); 276 | 277 | var childs = document.createElement('div'); 278 | childs.className = "Childs"; 279 | area.appendChild(childs); 280 | 281 | var c = value["childs"]; 282 | for(var i in c){ 283 | childs.appendChild(createContents(c[i])); 284 | } 285 | area.updateContents = function(value){ 286 | if (area.dataset.type === value["type"]){ 287 | var titleTag = 'H' + value["title_type"]; 288 | if (titleTag != title.nodeName){ 289 | var newTitle = document.createElement(titleTag); 290 | title.parentNode.insertBefore(newTitle,title); 291 | title.parentNode.removeChild(title); 292 | title = newTitle; 293 | } 294 | area.dataset.stat = value["stat"]; 295 | title.nodeName = 'H' + value["title_type"]; 296 | title.className = "Title" + value["title_type"]; 297 | title.textContent = value["title"]; 298 | date.textContent = (new Date(value["date"])).toLocaleString(); 299 | body.innerHTML = value["value"]; 300 | var nodes = body.querySelectorAll("img"); 301 | for(var i=0;i 0) { 26 | var id = mValue["id"]; 27 | var dir = AFL.sprintf("/Contents/%04d/%02d", Math.floor(id / 100) * 100, id % 100); 28 | 29 | //ファイル名の修正 30 | for (var i = 0; i < files.length; i++) { 31 | var file = files[i]; 32 | s = file.name.split(/(?=\.[^.]+$)/); 33 | var name = s[0] + (new Date).getTime(); 34 | if (s[1] != null) 35 | name += s[1]; 36 | file.name2 = name; 37 | } 38 | ADP.exec("Files.createDir",1,dir).on = function (r) { 39 | if (r != null && r.value) { 40 | GUI.uploadFiles(r.value, files, onComplete); 41 | } 42 | } 43 | } 44 | } 45 | function openFileView() { 46 | var id = mValue["id"]; 47 | var dir = AFL.sprintf("/Contents/%04d/%02d", Math.floor(id / 100) * 100, id % 100); 48 | var values = { 49 | "command": "createDir", "sessionHash": sessionStorage.getItem("sessionHash"), 50 | "parent": 1, "name": dir 51 | }; 52 | 53 | AFL.sendJson(SCRIPT_URL, values, function (r) { 54 | if (r != null && r.value) { 55 | var file = createFileWindow(r.value); 56 | file.addEvent("itemClick", onFile); 57 | } 58 | }); 59 | } 60 | function onComplete(files) { 61 | for (var i = 0; i < files.length; i++) { 62 | var file = files[i]; 63 | var id = file.id; 64 | var s; 65 | if (file.type.indexOf("image") != -1){ 66 | var node = editor.createElement("img"); 67 | node.style.maxWidth = "90%"; 68 | node.src = '?command=Files.download&id=' + id; 69 | editor.insertNode(node); 70 | }else{ 71 | s = AFL.sprintf("%s", file.id, file.name); 72 | editor.sendCommand('insertHTML', false, s); 73 | } 74 | } 75 | } 76 | 77 | function openFileView() { 78 | var id = mValue["id"]; 79 | var dir = AFL.sprintf("/Contents/%04d/%02d", Math.floor(id / 100) * 100, id % 100); 80 | ADP.exec("Files.createDir",1,dir).on = function (r) { 81 | if (r.value) { 82 | var file = createFileWindow(r.value); 83 | file.addEvent("itemClick", onFile); 84 | } 85 | } 86 | } 87 | function onFile(e) { 88 | //FileViewのオープン動作を抑制 89 | e.open = false; 90 | var id = e.value["id"]; 91 | var name = e.value["name"]; 92 | 93 | var ext = name.split('.'); 94 | var type = ""; 95 | if (ext.length > 1) { 96 | type = ext[ext.length - 1].toLowerCase(); 97 | } 98 | var g = ["jpg", "jpeg", "png", "svg"]; 99 | var flag = false; 100 | for (var index in g) { 101 | if (type == g[index]) { 102 | flag = true; 103 | break; 104 | } 105 | } 106 | var s; 107 | if (flag){ 108 | var node = editor.createElement("img"); 109 | node.style.maxWidth = "90%"; 110 | node.src = '?command=Files.download&id='+id; 111 | editor.insertNode(node); 112 | }else{ 113 | s = AFL.sprintf("%s", id, name); 114 | editor.sendCommand('insertHTML', false, s); 115 | } 116 | } 117 | 118 | function preview(){ 119 | mValue["date"] = (new Date(mTextDate.value + " " + mTextTime.value)).toISOString(); 120 | mValue["title"] = mTitle.value; 121 | mValue["stat"] = mCheckStat.checked?1:0; 122 | mValue["value"] = editor.getHtml(); 123 | Contents.updateContents(mValue); 124 | } 125 | function del(){ 126 | var id = mValue["id"]; 127 | Contents.deleteContents(id); 128 | } 129 | function onContentsDelete(e){ 130 | if (e.id == mValue["id"]) 131 | editor.close(); 132 | } 133 | 134 | var TITLE_TYPE = ["表示無", "表示大", "表示中", "表示小"]; 135 | var STAT_TYPE = ["仮状態","非表示","表示"]; 136 | var PAGE_TYPE = ["PAGE","TEXT","UPDATE"]; 137 | var mValue; 138 | var editor = createTextEditor(); //テキストエディタの作成 139 | editor.setSize(1000, 600); //サイズの指定 140 | editor.setPos(); //位置を中央に設定 141 | editor.addEvent("close",function(){ 142 | Contents.delEditor(editor); 143 | }); 144 | Contents.addEditor(editor); 145 | editor.getId = function(){ 146 | return mValue["id"]; 147 | } 148 | 149 | //editor.setHtml(node.innerHTML); //nodeの内容をエディタに設定 150 | 151 | //コントロールパネル作成(エディタのカスタマイズ) 152 | var panel = editor.getStdPanel(); 153 | panel.addButton("FILE",function(){ 154 | openFileView(); 155 | }); 156 | 157 | var panel = editor.addPanel(); 158 | panel.getClient().innerHTML = 159 | "表示" + 160 | "日付時間 "; 161 | panel.setSortZ(1); //パネルを一番上に 162 | var button = panel.getClient().querySelectorAll("button"); 163 | //保存処理 164 | button[0].addEventListener("click",save); 165 | button[1].addEventListener("click", preview); 166 | button[2].addEventListener("click", del); 167 | //入力用インスタンスの取得 168 | var input = panel.getClient().querySelectorAll("input"); 169 | mCheckStat = input[0]; 170 | mTextDate = input[1]; 171 | mTextTime = input[2]; 172 | mTextDate.addEventListener("click", function () { 173 | var cal = createCalendar(); 174 | cal.setPos(); 175 | cal.addEvent("clickDay", function (e) { 176 | mTextDate.value = e.date.toLocaleDateString(); 177 | cal.close(); 178 | }); 179 | }); 180 | 181 | var panel = editor.addPanel(); 182 | panel.getClient().innerHTML = 183 | ""; 184 | panel.setSortZ(1); //パネルを一番上に 185 | input = panel.getClient().querySelectorAll("input"); 186 | mTitle = input[0]; 187 | 188 | button = panel.getClient().querySelectorAll("button"); 189 | //ページタイプ 190 | mType = button[0]; 191 | mType.addEventListener("click", function () { 192 | var select = GUI.createSelectView(); 193 | for (var i = 0; i < PAGE_TYPE.length; i++) 194 | select.addText(PAGE_TYPE[i]); 195 | select.show(this); 196 | select.addEvent("select", function (e) { 197 | mType.textContent = e.value; 198 | mValue["type"] = e.value; 199 | }); 200 | }); 201 | 202 | //タイトルタイプ 203 | mTitleType = button[1]; 204 | mTitleType.addEventListener("click", function () { 205 | var select = GUI.createSelectView(); 206 | for(var i=0;i width) 40 | x = width - menu.offsetWidth; 41 | if (y + menu.offsetHeight > height) 42 | y = height - menu.offsetHeight; 43 | menu.style.left = x + "px"; 44 | menu.style.top = y + "px"; 45 | 46 | return menu; 47 | } 48 | (function(){ 49 | //PHP通信用アダプタの作成(グローバル) 50 | ADP = AFL.createAdapter("./",sessionStorage.getItem("sessionHash")); 51 | document.addEventListener("DOMContentLoaded",onLoad); 52 | 53 | //プログラム開始動作 54 | function onLoad(){ 55 | Contents.loadTitle(); 56 | //認証処理後、onStartを呼び出す 57 | SESSION.requestSession(onStart,false); 58 | 59 | } 60 | System = {}; 61 | System.reload = function(){ 62 | onStart(); 63 | } 64 | 65 | function onStart(){ 66 | GUI.rootWindow.removeChildAll(); 67 | 68 | ADP.exec("Params.getParams", [ 69 | "base_url", 70 | "base_adsense", "base_adsenseTop", "base_adsenseBottom", "base_adsenseInner", 71 | "base_rakutenTop", "base_rakutenBottom","base_rakutenInner", 72 | "base_amazonTop", "base_amazonBottom", "base_amazonInner", "base_amazonSide"]).on = 73 | function(value){ 74 | System.baseUrl = value["base_url"] 75 | System.adsense = { 76 | base: value["base_adsense"], 77 | top: value["base_adsenseTop"], 78 | bottom: value["base_adsenseBottom"], 79 | inner: value["base_adsenseInner"], 80 | side: value["base_adsenseSide"]} 81 | System.rakuten = { 82 | top: value["base_rakutenTop"], 83 | bottom: value["base_rakutenBottom"], 84 | inner: value["base_rakutenInner"], 85 | side: value["base_rakutenSide"] 86 | } 87 | System.amazon = { 88 | top: value["base_amazonTop"], 89 | bottom: value["base_amazonBottom"], 90 | inner: value["base_amazonInner"], 91 | side: value["base_amazonSide"] 92 | } 93 | } 94 | 95 | //画面上部を作成 96 | var top = GUI.createWindow(); 97 | top.setSize(0, 60); 98 | top.setChildStyle("top"); 99 | top.setClientClass("LayoutTop"); 100 | 101 | var title = document.createElement("div"); 102 | title.className = "topTitle"; 103 | top.getClient().appendChild(title); 104 | title.textContent = System.title; 105 | document.title = System.title; 106 | Contents.addEvent("title",function(){ 107 | title.textContent = System.title; 108 | document.title = System.title; 109 | }); 110 | 111 | var items = document.createElement("div"); 112 | items.className = "menuItems"; 113 | top.getClient().appendChild(items); 114 | 115 | //ユーザの表示 116 | var login = document.createElement("div"); 117 | System.login = login; 118 | login.className = "menuItem"; 119 | items.appendChild(login); 120 | login.addEventListener("click", function () { 121 | SESSION.createLoginWindow(onStart); 122 | }); 123 | System.login.textContent = SESSION.getUserName(); 124 | 125 | //パンくずリスト作成 126 | var breadcrumbList = document.createElement('script'); 127 | breadcrumbList.type='application/ld+json'; 128 | breadcrumbValue={ 129 | "@context": "http://schema.org", 130 | "@type": "BreadcrumbList","itemListElement":[]}; 131 | breadcrumbList.src = JSON.stringify(breadcrumbValue); 132 | document.head.appendChild(breadcrumbList); 133 | 134 | //管理メニューの表示 135 | if (SESSION.isAuthority("SYSTEM_ADMIN")){ 136 | var setting = document.createElement("div"); 137 | System.setting = setting; 138 | setting.className = "menuItem"; 139 | setting.textContent = "設定"; 140 | items.appendChild(setting); 141 | setting.addEventListener("click", function () { 142 | createSettingView(mainView); 143 | }); 144 | 145 | var file = document.createElement("div"); 146 | System.file = setting; 147 | file.className = "menuItem"; 148 | file.textContent = "FILE"; 149 | items.appendChild(file); 150 | file.addEventListener("click", function () { 151 | createFileWindow(); 152 | }); 153 | 154 | var visible = document.createElement("div"); 155 | System.visible = setting; 156 | visible.className = "menuItem"; 157 | visible.textContent = "表示"; 158 | items.appendChild(visible); 159 | visible.addEventListener("click", function () { 160 | var flag = !Contents.isVisible(); 161 | visible.textContent = flag?"表示":"非表示"; 162 | Contents.setVisible(flag); 163 | }); 164 | } 165 | 166 | var mainView = GUI.createWindow(); 167 | mainView.setChildStyle("client"); 168 | 169 | createContensView(mainView); 170 | 171 | //createImportView(); 172 | } 173 | 174 | // 175 | 176 | 177 | })(); -------------------------------------------------------------------------------- /JavaScript/PluginView.js: -------------------------------------------------------------------------------- 1 | function createPluginView(){ 2 | var win = GUI.createWindow(); 3 | ADP.exec("MG.getPlugins").on = function(values){ 4 | if (values === null) 5 | return; 6 | var client = win.getClient(); 7 | client.classList.add("BoxView"); 8 | 9 | for(var i=0;i
ユーザ名
"+ 14 | "
パスワード
"+ 15 | "
"; 16 | 17 | client.querySelector("button").addEventListener("click",function(){ 18 | var inputs = client.querySelectorAll("input"); 19 | ADP.exec("Session.createAdmin",inputs[0].value,inputs[1].value).on = function(value){ 20 | if(value){ 21 | win.close(); 22 | SESSION.requestSession(func); 23 | }else{ 24 | GUI.createMessageBox("エラー","管理者の作成に失敗"); 25 | } 26 | } 27 | }); 28 | return win; 29 | } 30 | //ログインウインドウの作成 31 | SESSION.createLoginWindow = function(func){ 32 | var win = GUI.createFrameWindow(); 33 | win.setTitle("ログイン"); 34 | win.setSize(300,200); 35 | win.setPos(); 36 | var client = win.getClient(); 37 | client.classList.add("ParamsEditView"); 38 | client.innerHTML = 39 | "
" + 40 | "
ユーザ名
" + 41 | "
パスワード
" + 42 | "
" + 43 | "
"; 44 | var input = client.querySelectorAll("input"); 45 | input[0].focus(); 46 | for(var i=0;i<2;i++) 47 | input[i].addEventListener("keydown",keydown); 48 | var button = client.querySelectorAll("button"); 49 | button[0].addEventListener("click",login); 50 | button[1].addEventListener("click",logout); 51 | function keydown(e){ 52 | if(e.keyCode == 13) 53 | login(); 54 | } 55 | function login(e){ 56 | var pass = CryptoJS.MD5(ADP.getSession() + CryptoJS.MD5(input[1].value).toString()).toString(); 57 | ADP.exec("Session.requestLogin", input[0].value, pass).on = 58 | function(r){ 59 | if(r == null) 60 | return; 61 | if(r.result == 0) 62 | return; 63 | sessionStorage.setItem("sessionHash",ADP.getSession()); 64 | win.close(); 65 | SESSION.sessionData = r; 66 | func(r); 67 | } 68 | 69 | if(e != null) 70 | e.preventDefault(); 71 | return false; 72 | } 73 | function logout(){ 74 | sessionStorage.removeItem("sessionHash"); 75 | ADP.setSession(null); 76 | win.close(); 77 | SESSION.requestSession(func); 78 | return false; 79 | } 80 | } 81 | //セッション情報照合と復元 82 | SESSION.requestSession = function (func, flag) { 83 | var win = GUI.createFrameWindow(); 84 | win.setTitle("認証情報"); 85 | win.setSize(300, 200); 86 | win.setPos(); 87 | 88 | var client = win.getClient(); 89 | client.classList.add("ParamsEditView"); 90 | client.innerHTML = "認証確認中"; 91 | 92 | ADP.exec("Session.requestSession").on = function (r) { 93 | if (r === null || r.result === 0) { 94 | sessionStorage.removeItem("sessionHash"); 95 | ADP.setSession(null); 96 | if (flag) 97 | requestLogin(); //セッションに照合失敗したのでリトライ 98 | else 99 | func(null); 100 | } else { 101 | sessionStorage.setItem("sessionHash", r.sessionHash); 102 | ADP.setSession(r.sessionHash); 103 | win.close(); 104 | if (r === null) { 105 | GUI.createMessageBox("エラー", "サーバ接続エラー"); 106 | return; 107 | } 108 | if (r.result === -1) { 109 | GUI.createMessageBox("エラー", "SQLiteのアクセス権を確認してください"); 110 | return; 111 | } 112 | if (r.result === -2) { 113 | SESSION.createLocalAdmin(func); 114 | return; 115 | } 116 | SESSION.sessionData = r; 117 | func(r); 118 | } 119 | win.close(); 120 | }; 121 | } 122 | SESSION.isAuthority = function(authority){ 123 | if (SESSION.sessionData && SESSION.sessionData.user && SESSION.sessionData.user.groups) 124 | return SESSION.sessionData.user.groups.indexOf(authority) >= 0; 125 | return false; 126 | } 127 | SESSION.getUserName = function(){ 128 | return SESSION.sessionData.user.name; 129 | } 130 | 131 | })(); 132 | -------------------------------------------------------------------------------- /JavaScript/SettingView.js: -------------------------------------------------------------------------------- 1 | function createSettingView(mainView) { 2 | mainView.removeChildAll(); 3 | //画面分割(横) 4 | var separate = GUI.createSeparate(200, "we"); 5 | mainView.addChild(separate, "client"); 6 | 7 | //ツリーメニューの作成 8 | var treeMenu = GUI.createTreeView(); 9 | separate.addSeparateChild(0, treeMenu, "client"); 10 | treeMenu.addEvent("select", function () { 11 | var parent = separate.getChild(1); 12 | parent.removeChildAll(); 13 | var proc = treeMenu.getSelectValue(); 14 | if (proc) { 15 | var w = proc(); 16 | if(w) 17 | separate.addSeparateChild(1, w, "client"); 18 | } 19 | 20 | }); 21 | 22 | var rootItem = treeMenu.getRootItem(); 23 | rootItem.setItemText("Menu一覧"); 24 | 25 | var item, subItem; 26 | item = rootItem.addItem("システム"); 27 | item.addItem("モジュール確認").setItemValue(createPluginView); 28 | item.addItem("データベース設定").setItemValue(createDatabaseView); 29 | item.addItem("ユーザ設定").setItemValue(createUserView); 30 | item.addItem("グループ設定").setItemValue(createGroupView); 31 | item.addItem("基本設定").setItemValue(createBaseSetView); 32 | item.addItem("広告").setItemValue(createAdsenseView); 33 | item.addItem("ログ").setItemValue(createLog); 34 | item.addItem("祝日設定").setItemValue(importHoliday); 35 | item.addItem("設定を閉じる").setItemValue(System.reload); 36 | } 37 | function createAdsenseView(parent){ 38 | var list = GUI.createListView(); 39 | list.addHeader("項目", 200); 40 | list.addHeader("データ", 300); 41 | list.addItem("AdSense広告審査コード"); 42 | list.addItem("AdSenseページ上部"); 43 | list.addItem("AdSenseページ下部"); 44 | list.addItem("AdSense記事内"); 45 | list.addItem("AdSenseサイド"); 46 | list.addItem("楽天記ページ上部"); 47 | list.addItem("楽天記ページ下部"); 48 | list.addItem("楽天記事内"); 49 | list.addItem("楽天サイド"); 50 | list.addItem("Amazonページ上部"); 51 | list.addItem("Amazonページ下部"); 52 | list.addItem("Amazon記事内"); 53 | list.addItem("Amazonサイド"); 54 | var label = [ 55 | "base_adsense", "base_adsenseTop", "base_adsenseBottom", "base_adsenseInner", "base_adsenseSide", 56 | "base_rakutenTop", "base_rakutenBottom", "base_rakutenInner", "base_rakutenSide", 57 | "base_amazonTop", "base_amazonBottom", "base_amazonInner", "base_amazonSide"]; 58 | 59 | list.addEvent("itemClick", function (e) { 60 | var index = e.itemIndex; 61 | var subIndex = e.itemSubIndex; 62 | if (subIndex != 1) 63 | return; 64 | 65 | var edit = list.editText(index, subIndex); 66 | edit.setMultiLine(true); 67 | edit.setHeight(100); 68 | edit.addEvent("enter", function (e) { 69 | ADP.exec("Params.setParam", label[index], e.value).on = 70 | function (flag) { 71 | if (flag) { 72 | Contents.loadTitle(); 73 | list.setItem(index, subIndex, e.value); 74 | } 75 | } 76 | }); 77 | 78 | }); 79 | 80 | list.load = function () { 81 | ADP.exec("Params.getParams", label).on = function (values) { 82 | if (values) { 83 | for (var i = 0; i < label.length; i++) 84 | list.setItem(i, 1, values[label[i]]); 85 | } 86 | } 87 | } 88 | list.load(); 89 | return list; 90 | 91 | } 92 | 93 | function createBaseSetView(parent) { 94 | var list = GUI.createListView(); 95 | list.addHeader("項目", 200); 96 | list.addHeader("データ", 300); 97 | 98 | list.addItem("URL"); 99 | list.addItem("タイトル"); 100 | list.addItem("説明"); 101 | list.addItem("アナリティクスID"); 102 | 103 | 104 | var label = ["base_url", "base_title", "base_info", "base_analytics"]; 105 | 106 | list.addEvent("itemClick", function (e) { 107 | var index = e.itemIndex; 108 | var subIndex = e.itemSubIndex; 109 | if (subIndex != 1) 110 | return; 111 | 112 | var edit = list.editText(index, subIndex); 113 | edit.addEvent("enter", function (e) { 114 | ADP.exec("Params.setParam", label[index], e.value).on = 115 | function (flag) { 116 | if (flag) { 117 | Contents.loadTitle(); 118 | list.setItem(index, subIndex, e.value); 119 | } 120 | } 121 | }); 122 | 123 | }); 124 | 125 | list.load = function () { 126 | ADP.exec("Params.getParams", label).on = function (values) { 127 | if (values){ 128 | for (var i = 0; i < label.length;i++) 129 | list.setItem(i, 1, values[label[i]]); 130 | } 131 | } 132 | } 133 | list.load(); 134 | return list; 135 | } -------------------------------------------------------------------------------- /JavaScript/TextEditor.js: -------------------------------------------------------------------------------- 1 | function createTextEditor(){ 2 | function convertLine(value){ 3 | //開業補正 4 | var s = value.replace(/(?!(\r\n|\n|\r))(
(?!(\r\n|\n|\r))/g, '
\n$1'); 7 | s = s.replace(/(\r\n|\n|\r){2}/g, '\n'); 8 | return s; 9 | } 10 | function drawColorPicker(button) { 11 | var frame = GUI.createFrameWindow(); 12 | var colorPicker = GUI.createColorPicker(); 13 | frame.setTitle("カラーピッカー"); 14 | colorPicker.setColor(button._color); 15 | colorPicker.addEvent("color",function (e) 16 | { 17 | var color = (255 << 24) + (e.r << 16) + (e.g << 8) + e.b; 18 | button._color = color; 19 | button.style.color = GUI.getARGB(color); 20 | }); 21 | 22 | frame.addChild(colorPicker,"client"); 23 | frame.setSize(400, 400); 24 | frame.setOrderSystem(true); 25 | frame.setPos(); 26 | } 27 | function createLink(select) 28 | { 29 | function onLink(e){ 30 | win.sendCommand("createLink",null,e.value); 31 | select.anchorNode.parentElement.target = '_blank'; 32 | input.close(); 33 | } 34 | var input = GUI.createTextInputWindow(); 35 | input.setTitle("リンク"); 36 | input.addEvent("enter",onLink); 37 | input.setOrderSystem(true); 38 | input.setSize(400,30); 39 | 40 | } 41 | 42 | function setPGCode(select){ 43 | var range = select.getRangeAt(0); 44 | var text = select.toString(); 45 | var text = text.replace( 46 | /["&'<>\n]/g, 47 | function (ch) { return { '
': '
\n','\n':'
\n','"':'"', '&':'&', '\'':''', '<':'<', '>':'>' }[ ch ]; } 48 | ); 49 | range.deleteContents(); 50 | range.insertNode(range.createContextualFragment("
" + text + "

")); 51 | updateHtmlTimer(); 52 | } 53 | function createStdPanel(){ 54 | function createButton(name,proc){ 55 | var button = document.createElement("button"); 56 | button.innerHTML = name; 57 | button.addEventListener("click",proc); 58 | return button; 59 | } 60 | function addButton(name,proc){ 61 | var button = createButton(name,proc); 62 | panel.getClient().appendChild(button); 63 | return button; 64 | } 65 | 66 | var panel = win.addPanel(); 67 | panel.addButton = addButton; 68 | var button; 69 | 70 | addButton("解",function(){win.sendCommand("removeFormat");}); 71 | addButton("",function(){win.sendCommand("bold");}); 72 | addButton("",function(){win.sendCommand("italic");}); 73 | addButton("",function(){win.sendCommand("underline");}); 74 | addButton("",function(){win.sendCommand("strikeThrough");}); 75 | addButton("A",function(){createLink(iframe.contentWindow.getSelection());}); 76 | addButton("CODE",function(){setPGCode(iframe.contentWindow.getSelection());}); 77 | 78 | //文字サイズ 79 | addButton("大",function(){ 80 | var r = this.getBoundingClientRect(); 81 | var select = GUI.createSelectView(); 82 | for(var i=1;i<=7;i++) 83 | select.addText(i); 84 | select.setSize(r.width,200); 85 | select.setPos(r.left,r.top+r.height); 86 | select.setOrderSystem(true); 87 | select.addEvent("select",function(e){win.sendCommand("fontSize",false,e.value);}); 88 | }); 89 | 90 | var group; 91 | //文字色 92 | group = document.createElement("span"); 93 | group.className="group"; 94 | panel.getClient().appendChild(group); 95 | button = createButton("色",function(){win.sendCommand("foreColor",false,colorButton.style.color);}); 96 | group.appendChild(button); 97 | var colorButton = createButton("■",function(){drawColorPicker(this);}); 98 | colorButton._color = 0xff000000; 99 | group.appendChild(colorButton); 100 | 101 | //背景色 102 | group = document.createElement("span"); 103 | group.className="group"; 104 | panel.getClient().appendChild(group); 105 | button = createButton("背",function(){win.sendCommand("backColor",false,colorButton2.style.color);}); 106 | group.appendChild(button); 107 | var colorButton2 = createButton("■",function(){drawColorPicker(this);}); 108 | colorButton2._color = 0xff000000; 109 | group.appendChild(colorButton2); 110 | 111 | return panel; 112 | } 113 | 114 | 115 | var win = GUI.createFrameWindow(); 116 | win.classList.add("TextEdit"); 117 | win.setTitle("テキストエディタ"); 118 | win.setSize(1000,600); 119 | 120 | win.addPanel = function(){ 121 | var panel = GUI.createPanel(); 122 | panel.getClient().classList.add("PanelArea"); 123 | win.addChild(panel,"top"); 124 | return panel; 125 | } 126 | win.createElement = function(name){ 127 | return iframe.contentDocument.createElement(name); 128 | } 129 | win.insertNode = function(node){ 130 | var r = iframe.contentDocument.getSelection().getRangeAt(0); 131 | r.deleteContents(); 132 | r.insertNode(node); 133 | updateHtmlTimer(); 134 | } 135 | win.sendCommand = function(a,b,c){ 136 | iframe.contentDocument.execCommand(a,b,c); 137 | } 138 | win.setHtml = function(value){ 139 | mText.value = value; 140 | mHtml.innerHTML = value; 141 | } 142 | win.getHtml = function(){ 143 | return convertLine(mHtml.innerHTML); 144 | } 145 | win.getHtmlBox = function(){ 146 | return mHtml; 147 | } 148 | win.getTextBox = function(){ 149 | return mText; 150 | } 151 | win.getStdPanel = function(){ 152 | return mPanel; 153 | } 154 | win.getSelect = function(){ 155 | return iframe.contentWindow.getSelection(); 156 | } 157 | 158 | 159 | //ウインドウ分割 160 | var separate = GUI.createSeparate(); 161 | separate.setSeparatePos(800,"we"); 162 | win.addChild(separate,"client"); 163 | var client0 = separate.getChild(0).getClient(); 164 | client0.classList.add("HtmlEditArea"); 165 | var client1 = separate.getChild(1).getClient(); 166 | 167 | //テキスト編集エリアの作成の作成 168 | var iframe = document.createElement("iframe"); 169 | client0.appendChild(iframe); 170 | iframe.contentDocument.head.innerHTML = 171 | ""; 172 | iframe.contentDocument.body.contentEditable = "true"; 173 | var mHtml = iframe.contentDocument.body; 174 | 175 | var mText = document.createElement("textarea"); 176 | client1.classList.add("TextEditArea"); 177 | client1.appendChild(mText); 178 | 179 | //編集内容の更新用 180 | var mHtmlTimer; 181 | var mTextTimer; 182 | function updateHtmlTimer(){ 183 | if(mHtmlTimer != null) 184 | clearTimeout(mHtmlTimer); 185 | mHtmlTimer = setTimeout(function(){ 186 | mHtmlTimer = null; 187 | var s = convertLine(mHtml.innerHTML); 188 | if(s != mText.value) 189 | mText.value = s; 190 | },500); 191 | } 192 | function updateTextTimer(){ 193 | if(mTextTimer != null) 194 | clearTimeout(mTextTimer); 195 | mTextTimer = setTimeout(function(){ 196 | mTextTimer = null; 197 | if(mHtml.innerHTML != mText.value) 198 | mHtml.innerHTML = mText.value; 199 | },500); 200 | } 201 | 202 | if(window.document.documentMode){ 203 | mHtml.addEventListener("keydown",function(){ 204 | updateHtmlTimer(); 205 | }); 206 | } 207 | else{ 208 | mHtml.addEventListener("input",function(){ 209 | updateHtmlTimer(); 210 | }); 211 | } 212 | 213 | mText.addEventListener("input",function(){ 214 | updateTextTimer(); 215 | }); 216 | function isEnd(node){ 217 | 218 | } 219 | mHtml.addEventListener("keydown",function(e){ 220 | switch(e.keyCode){ 221 | case 40: 222 | var select = iframe.contentDocument.getSelection(); 223 | var anchorNode = select.anchorNode; 224 | var anchorOffset = select.anchorOffset; 225 | if(anchorNode.textContent.length === anchorOffset){ 226 | select.modify('move','forward',"line"); 227 | if(anchorNode == select.anchorNode && anchorOffset == select.anchorOffset){ 228 | win.sendCommand("insertHtml",false,"

"); 229 | updateHtmlTimer(); 230 | } 231 | e.preventDefault(); 232 | } 233 | 234 | //return false; 235 | // var range = select.getRangeAt(0); 236 | // var anchorNode = select.anchorNode; 237 | // var anchorOffset = select.anchorOffset; 238 | // //console.log(anchor); 239 | // select.selectAllChildren(mHtml); 240 | // select.anchorNode = anchorNode; 241 | // select.offsetOffset = anchorOffset; 242 | 243 | //console.log(select.toString()); 244 | //select.extend(mHtml,10); 245 | // var range = iframe.contentDocument.getSelection().getRangeAt(0); 246 | 247 | // range.setEnd(range.get) 248 | // console.log(isEnd(range.endContainer()); 249 | break; 250 | } 251 | //console.log(e.keyCode); 252 | // if(e.keyCode == 13){ 253 | // win.sendCommand("insertHtml",false,"
\u200C"); 254 | // e.preventDefault(); 255 | // } 256 | 257 | }); 258 | function insertImage(files){ 259 | //画像ファイルならDataURLに変換して貼り付ける 260 | for(var i=0;i\n\t ])/g, 281 | function( ch ) 282 | { return { 283 | '"':'"', '&':'&', '\'':''', '<':'<', '>':'>','\n':'
', 284 | ' ':' ','\t':'    ' }[ ch ]; }); 285 | //win.sendCommand("insertText", false, text); 286 | win.sendCommand("insertHtml", false, text); 287 | 288 | } 289 | e.preventDefault(); 290 | }); 291 | mHtml.addEventListener("drop",function(e){ 292 | //insertImage(e.dataTransfer.files); 293 | //e.preventDefault(); 294 | }); 295 | mHtml.ondragover = function (e) { 296 | e.preventDefault(); 297 | } 298 | var mPanel = createStdPanel(); 299 | 300 | 301 | mHtml.focus(); 302 | return win; 303 | } 304 | -------------------------------------------------------------------------------- /JavaScript/UserView.js: -------------------------------------------------------------------------------- 1 | function createUserView(){ 2 | var win = GUI.createWindow(); 3 | 4 | if(!SESSION.isAuthority('SYSTEM_ADMIN')){ 5 | GUI.createMessageBox("エラー","権限がありません",["OK"]); 6 | return win; 7 | } 8 | 9 | var separate = GUI.createSeparate(400,"ns"); 10 | win.addChild(separate,"client"); 11 | 12 | 13 | var panel = GUI.createPanel(); 14 | separate.getChild(0).addChild(panel,"top"); 15 | panel.getClient().innerHTML = "ユーザ設定 "; 16 | 17 | var buttons = panel.getClient().querySelectorAll("button"); 18 | for(var i=0;i= '0' && format.charAt(i) <= '9'; i++) { 55 | num *= 10; 56 | num += parseInt(format.charAt(i)); 57 | } 58 | switch (format.charAt(i)) { 59 | case 's': 60 | var work = String(args[paramIndex++]); 61 | var len = num - work.length; 62 | dest += work; 63 | var len = num - work.length; 64 | if (len > 0) { 65 | for (j = 0; j < len; j++) 66 | dest += ' '; 67 | } 68 | break; 69 | case 'd': 70 | var work = String(args[paramIndex++]); 71 | var len = num - work.length; 72 | if (len > 0) { 73 | var j; 74 | var c; 75 | if (flagZero) 76 | c = '0'; 77 | else 78 | c = ' '; 79 | for (j = 0; j < len; j++) 80 | dest += c; 81 | } 82 | dest += work; 83 | } 84 | } 85 | else 86 | dest += format.charAt(i); 87 | } 88 | return dest; 89 | } 90 | 91 | //--------------------------------------- 92 | //文字列の置換 93 | // 引数 src 元文字列 94 | // datas data[置換元] = 置換後 95 | // 戻り値 生成文字列 96 | function replaceText(src, datas) { 97 | var dest = new String(); 98 | var i; 99 | var length = src.length; 100 | var flag; 101 | for (i = 0; i < length; i++) { 102 | flag = true; 103 | for (index in datas) { 104 | var data = datas[index]; 105 | if (src.substr(i, index.length).indexOf(index) == 0) { 106 | dest += data; 107 | flag = false; 108 | i += index.length - 1; 109 | break; 110 | } 111 | } 112 | if (flag) 113 | dest += src.charAt(i); 114 | } 115 | return dest; 116 | } 117 | 118 | //--------------------------------------- 119 | //アドレスの取得、パラメータの削除 120 | // 引数 無し 121 | // 戻り値 生成文字列 122 | function getURL() { 123 | var i; 124 | var url = ''; 125 | var src = document.location.href; 126 | for (i = 0; src.charAt(i) && src.charAt(i) != '?' && src.charAt(i) != '#'; i++) 127 | url += src.charAt(i); 128 | return url; 129 | } 130 | 131 | //--------------------------------------- 132 | //アドレスの取得、ファイル名の削除 133 | // 引数 無し 134 | // 戻り値 生成文字列 135 | function getPATH() { 136 | var i; 137 | var path = document.location.href; 138 | var index = path.lastIndexOf("/"); 139 | if (index >= 0) 140 | path = path.substring(0, index + 1); 141 | return path; 142 | } 143 | //--------------------------------------------------------- 144 | //Cookie設定 145 | // 引数 name 名前 146 | // value 値 147 | // 戻り値 無し 148 | AFL.setCookie = function (name, value) { 149 | if (value != null) { 150 | var date = new Date(); 151 | date.setDate(date.getDate() + 30); 152 | 153 | document.cookie = 154 | encodeURI(name) + "=" + encodeURI(value) + "; expires=" + date.toGMTString() + ";path=/;"; 155 | } 156 | else { 157 | var date = new Date(); 158 | date.setDate(date.getDate() - 1); 159 | document.cookie = encodeURI(name) + "= ; expires=" + date.toGMTString() + ";"; 160 | } 161 | } 162 | 163 | AFL.getParams = function(){ 164 | var params = {}; 165 | var pair=location.search.substring(1).split('&'); 166 | for(var index in pair) { 167 | var value = pair[index]; 168 | var data = value.split('='); 169 | params[data[0]] = data[1]; 170 | } 171 | return params; 172 | } 173 | //--------------------------------------------------------- 174 | //Cookie取得 175 | // 引数 name 名前 176 | // 戻り値 値 177 | AFL.getCookie = function (name) { 178 | //クッキー分解用 179 | function getCookies() { 180 | var dest = Array(); 181 | var cookieData = document.cookie + ";" 182 | var index1 = 0; 183 | var index2; 184 | while ((index2 = cookieData.indexOf("=", index1)) >= 0) { 185 | var name = cookieData.substring(index1, index2); 186 | var value = ''; 187 | index1 = index2 + 1; 188 | index2 = cookieData.indexOf(";", index1); 189 | if (index2 == -1) 190 | break; 191 | value = cookieData.substring(index1, index2); 192 | if (dest[decodeURI(name)] == undefined) 193 | dest[decodeURI(name)] = decodeURI(value); 194 | index1 = index2 + 1; 195 | for (; cookieData.charAt(index1) == ' '; index1++); 196 | } 197 | return dest; 198 | } 199 | var cookies = getCookies(); 200 | return cookies[name]; 201 | } 202 | 203 | //--------------------------------------------------------- 204 | //Ajax用インスタンスの作成 205 | // 引数 無し 206 | // 戻り値 Ajax用インスタンス 207 | AFL.getRequest = function () { 208 | var xmlHttp = null; 209 | if (window.XMLHttpRequest) { 210 | xmlHttp = new XMLHttpRequest(); 211 | } 212 | else if (window.ActiveXObject) { 213 | xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 214 | if (!xmlHttp) 215 | xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 216 | } 217 | return xmlHttp; 218 | } 219 | //--------------------------------------------------------- 220 | //Ajaxによるデータ送信 221 | // 引数 url 接続先アドレス 222 | // getData 送信用GETパラメータ 223 | // postData 送信用POSTパラメータ 224 | // proc 送信完了後のコールバックファンクション(null可) 225 | // 戻り値 procがnullの場合は、同期通信後データを返す 226 | AFL.send = function (url, getData, postData, proc) { 227 | var xmlHttp = AFL.getRequest(); 228 | var methodGET = ""; 229 | if (getData) { 230 | var urlGET = url.indexOf('?'); 231 | for (name in getData) { 232 | if (methodGET.length == 0 && urlGET == -1) 233 | methodGET += '?'; 234 | else 235 | methodGET += '&'; 236 | methodGET += encodeURIComponent(name) + '=' + encodeURIComponent(getData[name]); 237 | } 238 | } 239 | 240 | try { 241 | url += methodGET; 242 | if (proc == null) 243 | xmlHttp.open('POST', url, false); 244 | else { 245 | xmlHttp.onreadystatechange = function () { 246 | if (xmlHttp.readyState == 4) { 247 | proc(xmlHttp.responseText); 248 | } 249 | } 250 | xmlHttp.open('POST', url, true); 251 | } 252 | var data = new Uint8Array(postData); 253 | xmlHttp.send(data); 254 | } 255 | catch (e) { 256 | alert(e); 257 | alert("読み込みエラー"); 258 | if (proc != null) 259 | proc(null); 260 | return null; 261 | } 262 | return xmlHttp.responseText; 263 | 264 | } 265 | //--------------------------------------------------------- 266 | //Ajaxによるファイル送信 267 | // 引数 url 接続先アドレス 268 | // getData 送信用GETパラメータ 269 | // postData 送信ファイルデータ 270 | // proc 送信完了後のコールバックファンクション(null可) 271 | // 戻り値 procがnullの場合は、同期通信後データを返す 272 | AFL.sendFile = function (url, getData, postData, proc,progress) { 273 | var xmlHttp = AFL.getRequest(); 274 | var flag = false; 275 | try{ 276 | xmlHttp.responseType = type==null?"json":type; 277 | }catch(e){flag=true;} 278 | 279 | var methodGET = ""; 280 | if (getData) { 281 | var urlGET = url.indexOf('?'); 282 | for (name in getData) { 283 | if (methodGET.length == 0 && urlGET == -1) 284 | methodGET += '?'; 285 | else 286 | methodGET += '&'; 287 | methodGET += encodeURIComponent(name) + '=' + encodeURIComponent(getData[name]); 288 | } 289 | } 290 | 291 | try { 292 | 293 | url += methodGET; 294 | 295 | xmlHttp.onreadystatechange = function () { 296 | if (xmlHttp.readyState == 4) { 297 | var obj = null; 298 | try 299 | { 300 | if(flag) 301 | obj = JSON.parse(xmlHttp.response); 302 | else 303 | obj = xmlHttp.response; 304 | 305 | } catch (e) 306 | { 307 | proc(null); 308 | return; 309 | } 310 | if(AFL.sendProc != null) 311 | AFL.sendProc(obj); 312 | proc(obj); 313 | } 314 | } 315 | if(progress != null){ 316 | xmlHttp.upload.onprogress = function(e){ 317 | progress(e); 318 | } 319 | } 320 | xmlHttp.open('POST', url, true); 321 | 322 | var data = new Uint8Array(postData); 323 | var pt = 0; 324 | if (sessionStorage.getItem("Session")) 325 | xmlHttp.setRequestHeader("X-Session", sessionStorage.getItem("Session")); 326 | xmlHttp.send(data); 327 | } 328 | catch (e) { 329 | alert(e); 330 | alert("読み込みエラー"); 331 | if (proc != null) 332 | proc(xmlHttp, data); 333 | return null; 334 | } 335 | return xmlHttp; 336 | 337 | } 338 | //--------------------------------------------------------- 339 | //AjaxにJSONデータの送信 340 | // 引数 url 接続先アドレス 341 | // data 送信用オブジェクト 342 | // proc 送信完了後のコールバックファンクション(null可) 343 | // 戻り値 procがnullの場合は、同期通信後データを返す 344 | AFL.sendJson = function (url, data, proc,type) { 345 | var xmlHttp = AFL.getRequest(); 346 | var flag = false; 347 | try{ 348 | xmlHttp.responseType = type==null?"json":type; 349 | }catch(e){flag=true;} 350 | try { 351 | if (proc == null) { 352 | xmlHttp.open('POST', url, false); 353 | return JSON.parse(xmlHttp.responseText); 354 | } 355 | else { 356 | xmlHttp.onreadystatechange = function () { 357 | if (xmlHttp.readyState == 4) { 358 | var obj = null; 359 | try 360 | { 361 | if(flag) 362 | obj = JSON.parse(xmlHttp.response); 363 | else 364 | obj = xmlHttp.response; 365 | 366 | } catch (e) 367 | { 368 | proc(null); 369 | return; 370 | } 371 | if(AFL.sendProc != null) 372 | AFL.sendProc(obj); 373 | proc(obj); 374 | } 375 | } 376 | } 377 | if (data == null) { 378 | xmlHttp.open('GET', url, true); 379 | xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 380 | xmlHttp.send(null); 381 | } 382 | else { 383 | xmlHttp.open('POST', url, true); 384 | xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 385 | if (sessionStorage.getItem("Session")) 386 | xmlHttp.setRequestHeader("X-Session", sessionStorage.getItem("Session")); 387 | xmlHttp.send(JSON.stringify(data)); 388 | } 389 | } 390 | catch (e) { 391 | alert("読み込みエラー"); 392 | proc(null); 393 | return null; 394 | } 395 | return null; 396 | } 397 | 398 | AFL.createAdapter = function(scriptUrl,sessionHash){ 399 | var adapter = {"url":scriptUrl,"sessionHash":sessionHash}; 400 | 401 | var functions = []; 402 | function connectServer() { 403 | if (functions.length === 0) 404 | return; 405 | var functions2 = functions; 406 | functions = []; 407 | var values = { "command": "exec", "sessionHash": adapter.sessionHash, "functions": functions2 }; 408 | AFL.sendJson(adapter.url, values, function (r) { 409 | var p = null; 410 | var index = 0; 411 | for (var i in functions2) { 412 | var func = functions2[i]; 413 | if (func.proc !== p) { 414 | if (p) { 415 | if (r === null || r.result == 0) 416 | p.on(null); 417 | else 418 | p.on(i - index == 1 ? r.values[index] : r.values.slice(index, i)); 419 | } 420 | index = i; 421 | p = func.proc; 422 | } 423 | } 424 | if (r === null || r.result == 0) 425 | p.on(null); 426 | else 427 | p.on(i - index == 0 ? r.values[index] : r.values.slice(index, i)); 428 | }); 429 | 430 | } 431 | adapter.exec = function(){ 432 | if(arguments.length == 0) 433 | return; 434 | var proc = {on:null}; 435 | if(arguments[0] instanceof Array) 436 | for(var i=0;i>>2]|=(a[g>>>2]>>>24-8*(g%4)&255)<<24-8*((j+g)%4);else if(65535>>2]=a[g>>>2];else h.push.apply(h,a);this.sigBytes+=b;return this},clamp:function(){var b=this.words,h=this.sigBytes;b[h>>>2]&=4294967295<< 9 | 32-8*(h%4);b.length=s.ceil(h/4)},clone:function(){var b=r.clone.call(this);b.words=this.words.slice(0);return b},random:function(b){for(var h=[],a=0;a>>2]>>>24-8*(j%4)&255;g.push((k>>>4).toString(16));g.push((k&15).toString(16))}return g.join("")},parse:function(b){for(var a=b.length,g=[],j=0;j>>3]|=parseInt(b.substr(j, 10 | 2),16)<<24-4*(j%8);return new q.init(g,a/2)}},a=v.Latin1={stringify:function(b){var a=b.words;b=b.sigBytes;for(var g=[],j=0;j>>2]>>>24-8*(j%4)&255));return g.join("")},parse:function(b){for(var a=b.length,g=[],j=0;j>>2]|=(b.charCodeAt(j)&255)<<24-8*(j%4);return new q.init(g,a)}},u=v.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(g){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}}, 11 | g=l.BufferedBlockAlgorithm=r.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(b){"string"==typeof b&&(b=u.parse(b));this._data.concat(b);this._nDataBytes+=b.sigBytes},_process:function(b){var a=this._data,g=a.words,j=a.sigBytes,k=this.blockSize,m=j/(4*k),m=b?s.ceil(m):s.max((m|0)-this._minBufferSize,0);b=m*k;j=s.min(4*b,j);if(b){for(var l=0;l>>32-j)+k}function m(a,k,b,h,l,j,m){a=a+(k&h|b&~h)+l+m;return(a<>>32-j)+k}function l(a,k,b,h,l,j,m){a=a+(k^b^h)+l+m;return(a<>>32-j)+k}function n(a,k,b,h,l,j,m){a=a+(b^(k|~h))+l+m;return(a<>>32-j)+k}for(var r=CryptoJS,q=r.lib,v=q.WordArray,t=q.Hasher,q=r.algo,a=[],u=0;64>u;u++)a[u]=4294967296*s.abs(s.sin(u+1))|0;q=q.MD5=t.extend({_doReset:function(){this._hash=new v.init([1732584193,4023233417,2562383102,271733878])}, 15 | _doProcessBlock:function(g,k){for(var b=0;16>b;b++){var h=k+b,w=g[h];g[h]=(w<<8|w>>>24)&16711935|(w<<24|w>>>8)&4278255360}var b=this._hash.words,h=g[k+0],w=g[k+1],j=g[k+2],q=g[k+3],r=g[k+4],s=g[k+5],t=g[k+6],u=g[k+7],v=g[k+8],x=g[k+9],y=g[k+10],z=g[k+11],A=g[k+12],B=g[k+13],C=g[k+14],D=g[k+15],c=b[0],d=b[1],e=b[2],f=b[3],c=p(c,d,e,f,h,7,a[0]),f=p(f,c,d,e,w,12,a[1]),e=p(e,f,c,d,j,17,a[2]),d=p(d,e,f,c,q,22,a[3]),c=p(c,d,e,f,r,7,a[4]),f=p(f,c,d,e,s,12,a[5]),e=p(e,f,c,d,t,17,a[6]),d=p(d,e,f,c,u,22,a[7]), 16 | c=p(c,d,e,f,v,7,a[8]),f=p(f,c,d,e,x,12,a[9]),e=p(e,f,c,d,y,17,a[10]),d=p(d,e,f,c,z,22,a[11]),c=p(c,d,e,f,A,7,a[12]),f=p(f,c,d,e,B,12,a[13]),e=p(e,f,c,d,C,17,a[14]),d=p(d,e,f,c,D,22,a[15]),c=m(c,d,e,f,w,5,a[16]),f=m(f,c,d,e,t,9,a[17]),e=m(e,f,c,d,z,14,a[18]),d=m(d,e,f,c,h,20,a[19]),c=m(c,d,e,f,s,5,a[20]),f=m(f,c,d,e,y,9,a[21]),e=m(e,f,c,d,D,14,a[22]),d=m(d,e,f,c,r,20,a[23]),c=m(c,d,e,f,x,5,a[24]),f=m(f,c,d,e,C,9,a[25]),e=m(e,f,c,d,q,14,a[26]),d=m(d,e,f,c,v,20,a[27]),c=m(c,d,e,f,B,5,a[28]),f=m(f,c, 17 | d,e,j,9,a[29]),e=m(e,f,c,d,u,14,a[30]),d=m(d,e,f,c,A,20,a[31]),c=l(c,d,e,f,s,4,a[32]),f=l(f,c,d,e,v,11,a[33]),e=l(e,f,c,d,z,16,a[34]),d=l(d,e,f,c,C,23,a[35]),c=l(c,d,e,f,w,4,a[36]),f=l(f,c,d,e,r,11,a[37]),e=l(e,f,c,d,u,16,a[38]),d=l(d,e,f,c,y,23,a[39]),c=l(c,d,e,f,B,4,a[40]),f=l(f,c,d,e,h,11,a[41]),e=l(e,f,c,d,q,16,a[42]),d=l(d,e,f,c,t,23,a[43]),c=l(c,d,e,f,x,4,a[44]),f=l(f,c,d,e,A,11,a[45]),e=l(e,f,c,d,D,16,a[46]),d=l(d,e,f,c,j,23,a[47]),c=n(c,d,e,f,h,6,a[48]),f=n(f,c,d,e,u,10,a[49]),e=n(e,f,c,d, 18 | C,15,a[50]),d=n(d,e,f,c,s,21,a[51]),c=n(c,d,e,f,A,6,a[52]),f=n(f,c,d,e,q,10,a[53]),e=n(e,f,c,d,y,15,a[54]),d=n(d,e,f,c,w,21,a[55]),c=n(c,d,e,f,v,6,a[56]),f=n(f,c,d,e,D,10,a[57]),e=n(e,f,c,d,t,15,a[58]),d=n(d,e,f,c,B,21,a[59]),c=n(c,d,e,f,r,6,a[60]),f=n(f,c,d,e,z,10,a[61]),e=n(e,f,c,d,j,15,a[62]),d=n(d,e,f,c,x,21,a[63]);b[0]=b[0]+c|0;b[1]=b[1]+d|0;b[2]=b[2]+e|0;b[3]=b[3]+f|0},_doFinalize:function(){var a=this._data,k=a.words,b=8*this._nDataBytes,h=8*a.sigBytes;k[h>>>5]|=128<<24-h%32;var l=s.floor(b/ 19 | 4294967296);k[(h+64>>>9<<4)+15]=(l<<8|l>>>24)&16711935|(l<<24|l>>>8)&4278255360;k[(h+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;a.sigBytes=4*(k.length+1);this._process();a=this._hash;k=a.words;for(b=0;4>b;b++)h=k[b],k[b]=(h<<8|h>>>24)&16711935|(h<<24|h>>>8)&4278255360;return a},clone:function(){var a=t.clone.call(this);a._hash=this._hash.clone();return a}});r.MD5=t._createHelper(q);r.HmacMD5=t._createHmacHelper(q)})(Math); 20 | -------------------------------------------------------------------------------- /PHP/LocalDB.php: -------------------------------------------------------------------------------- 1 | connect(LOCAL_DB); 6 | } 7 | } 8 | ?> -------------------------------------------------------------------------------- /PHP/MainDB.php: -------------------------------------------------------------------------------- 1 | connect($params["POSTGRES_ADR"],$params["POSTGRES_USER"],$params["POSTGRES_PASS"],$params["POSTGRES_DB"]); 11 | } 12 | } 13 | ?> -------------------------------------------------------------------------------- /PHP/Manager.php: -------------------------------------------------------------------------------- 1 | getMethod($func)->getNumberOfRequiredParameters(); 56 | if(count($func_info["params"]) < $count){ 57 | $errInfo = $func_info["function"].":パラメータが足りない"; 58 | Log::output($func_info["function"],$errInfo); 59 | break; 60 | } 61 | 62 | //命令の実行 63 | try{ 64 | $values[] = $class::$func(...$func_info["params"]); 65 | Log::output($func_info["function"],'実行'); 66 | }catch(Exception $e){ 67 | Log::output($func_info["function"],'異常終了'); 68 | } 69 | } 70 | //全ての命令が実行できたか? 71 | if(count($values) != count($funcs)) 72 | return ["result"=>0,"message"=>"execの実行失敗","info"=>$errInfo]; 73 | //データを返す 74 | return ["result"=>1,"message"=>"execの実行","values"=>$values]; 75 | }else{ 76 | //クラス名とファンクションを分ける 77 | $funcName = MG::getCommand(); 78 | $name = explode(".",$funcName,2); 79 | if(count($name) != 2){ 80 | $errInfo = $funcName.":クラスが指定されていない"; 81 | Log::output($funcName,$errInfo); 82 | return ["result"=>0,"message"=>"実行失敗","info"=>$errInfo]; 83 | } 84 | $class = $name[0]; 85 | $func = DECORATION.$name[1]; 86 | //実行可能か判断 87 | if(!property_exists($class,"JS_ENABLE") || !method_exists($class,$func)){ 88 | $errInfo = $funcName.":実行可能な命令が存在しない"; 89 | Log::output($funcName,$errInfo); 90 | return ["result"=>0,"message"=>"実行失敗","info"=>$errInfo]; 91 | } 92 | //命令の実行 93 | try{ 94 | $values[] = $class::$func(); 95 | Log::output($funcName,'実行'); 96 | }catch(Exception $e){ 97 | Log::output($funcName,'異常終了'); 98 | } 99 | //データを返す 100 | return ["result"=>1,"message"=>"実行","values"=>$values]; 101 | } 102 | 103 | return null; 104 | } 105 | 106 | public static function getParam($name){ 107 | if(Self::$mParams === null){ 108 | if(isset($_GET["command"])){ 109 | Self::$mCommand = $_GET["command"]; 110 | Self::$mParams = array(); 111 | }else{ 112 | $json_string = file_get_contents('php://input'); 113 | Self::$mParams = json_decode($json_string,true); 114 | Self::$mCommand = isset(Self::$mParams["command"])?Self::$mParams["command"]:""; 115 | } 116 | } 117 | if(isset(Self::$mParams[$name])){ 118 | return Self::$mParams[$name]; 119 | } 120 | if(isset($_GET[$name])) 121 | return $_GET[$name]; 122 | return null; 123 | } 124 | public static function isParams($values){ 125 | foreach($values as $value){ 126 | if(Self::getParam($value) === null) 127 | return false; 128 | } 129 | return true; 130 | } 131 | public static function isParamsOr($values){ 132 | foreach($values as $value){ 133 | if(Self::getParam($value) !== null) 134 | return true; 135 | } 136 | return false; 137 | } 138 | public static function setSessionHash($hash){ 139 | Self::$mSessionHash = $hash; 140 | } 141 | public static function getSessionHash(){ 142 | if(Self::$mSessionHash == null){ 143 | Self::$mSessionHash = Self::getParam("sessionHash"); 144 | } 145 | return Self::$mSessionHash; 146 | } 147 | public static function getCommand(){ 148 | if(Self::$mCommand !== null) 149 | return Self::$mCommand; 150 | return Self::getParam("command"); 151 | } 152 | public static function DB(){ 153 | if(Self::$mDB === null){ 154 | Self::$mDB = new MainDB(); 155 | Self::$mDB->setOnError("MG::errorDB"); 156 | } 157 | return Self::$mDB; 158 | } 159 | public static function LDB(){ 160 | if(Self::$mLocalDB === null){ 161 | Self::$mLocalDB = new LocalDB(LOCAL_DB); 162 | } 163 | return Self::$mLocalDB; 164 | } 165 | public static function getSession(){ 166 | if(Self::$mSession == null){ 167 | Self::$mSession = Session::getSessionValues(); 168 | } 169 | return Self::$mSession; 170 | } 171 | public static function initDB(){ 172 | $plugins = Self::getPlugins(); 173 | foreach($plugins as $plugin){ 174 | 175 | } 176 | } 177 | public static function getPlugins(){ 178 | $files = scandir(dirname(__FILE__).MODULE_PATH); 179 | $plugins = []; 180 | foreach($files as $file){ 181 | $name = explode(".",$file,2); 182 | if(count($name) === 2 && $name[1] === "php"){ 183 | if(defined($name[0]."::INFO")){ 184 | $info = $name[0]::INFO; 185 | $info['CLASS'] = $name[0]; 186 | $plugins[] = $info; 187 | } 188 | } 189 | } 190 | return $plugins; 191 | } 192 | public static function getUserId(){ 193 | $session = Self::getSession(); 194 | if($session == null) 195 | return 0; 196 | return $session["users_id"]; 197 | } 198 | public static function getUserCode(){ 199 | $session = Self::getSession(); 200 | if($session == null) 201 | return 0; 202 | return Users::getUserIdFromMail($session["users_id"]); 203 | } 204 | public static function isAdmin(){ 205 | return Self::isAuthority("SYSTEM_ADMIN"); 206 | } 207 | public static function isAuthority($authority){ 208 | $session = Self::getSession(); 209 | if(!$session) 210 | return false; 211 | if($session["users_id"] == -1) 212 | return true; 213 | return array_search($authority,$session["groups"]) !== false; 214 | } 215 | public static function getUserGroups($userId){ 216 | if(!method_exists("Users","getGroupNames")) 217 | return []; 218 | return Users::getGroupNames($userId); 219 | } 220 | public static function JS_getPlugins(){ 221 | return Self::getPlugins(); 222 | } 223 | 224 | public static function JS_setDatabase($adr,$user,$pass,$name){ 225 | if(!Self::isAuthority("SYSTEM_ADMIN")) 226 | return false; 227 | Params::setParam("POSTGRES_ADR",$adr); 228 | Params::setParam("POSTGRES_USER",$user); 229 | Params::setParam("POSTGRES_PASS",$pass); 230 | Params::setParam("POSTGRES_DB",$name); 231 | 232 | $db = new PostgreSQL(); 233 | if($db->connect($adr,$user,$pass,$name)) 234 | return true; 235 | 236 | if($db->connect($adr,$user,$pass,"postgres")){ 237 | return $db->exec("create database $name") === 0; 238 | } 239 | return false; 240 | } 241 | public static function JS_getDatabase(){ 242 | if(!Self::isAuthority("SYSTEM_ADMIN")) 243 | return null; 244 | return Params::getParams("POSTGRES_ADR","POSTGRES_USER","POSTGRES_PASS","POSTGRES_DB"); 245 | } 246 | 247 | 248 | } 249 | -------------------------------------------------------------------------------- /PHP/Modules/Calendar.php: -------------------------------------------------------------------------------- 1 | "カレンダープラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"カレンダー情報の管理", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["holiday_date",0,1]] 10 | ]; 11 | 12 | public static function initModule(){ 13 | MG::DB()->exec("create table IF NOT EXISTS holiday(holiday_date date primary key,holiday_name text)"); 14 | } 15 | public static function JS_importHoliday(){ 16 | if(!MG::isAdmin()) 17 | return ["result"=>0,"message"=>"休日インポート 権限エラー"]; 18 | if(Self::importHoliday()) 19 | return ["result"=>1,"message"=>"休日インポート完了"]; 20 | return ["result"=>0,"message"=>"休日インポートデータ取得失敗"]; 21 | } 22 | public static function JS_getHoliday($start,$end){ 23 | return Self::getHoliday($start,$end); 24 | } 25 | public static function JS_setHoliday($date,$name){ 26 | if(!MG::isAdmin()) 27 | return false; 28 | return Self::setHoliday([$date,$name]); 29 | } 30 | static function getHoliday($start,$end){ 31 | return MG::DB()->queryData2("select * from holiday where holiday_date>=? and holiday_date<=?", 32 | $start,$end); 33 | } 34 | 35 | public static function importHoliday(){ 36 | $url = "http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu_kyujitsu.csv"; 37 | $values = []; 38 | // fopenでファイルを開く('r'は読み込みモードで開く) 39 | $fp = fopen($url, 'r'); 40 | if($fp == null) 41 | return null; 42 | // whileで行末までループ処理 43 | if(!feof($fp)) 44 | fgets($fp); 45 | while (!feof($fp)){ 46 | $txt = fgets($fp); 47 | $txt = mb_convert_encoding($txt, "UTF8", "SJIS"); 48 | $value = explode(",",$txt); 49 | if(count($value) > 0) 50 | { 51 | $value[0] = date($value[0]); 52 | $value[1] = rtrim($value[1]); 53 | $values[] = $value; 54 | } 55 | } 56 | fclose($fp); 57 | 58 | Self::setHoliday($values); 59 | return true; 60 | } 61 | public static function setHoliday($values){ 62 | //MG::getDB()->exec("begin"); 63 | for($i=0;$iexec("delete from holiday where date(holiday_date)=date(?)",[$value[0]]); 67 | } 68 | else 69 | MG::DB()->replace("holiday",["holiday_date"],["holiday_date"=>$value[0],"holiday_name"=>$value[1]]); 70 | } 71 | //MG::getDB()->exec("commit"); 72 | return true; 73 | } 74 | } -------------------------------------------------------------------------------- /PHP/Modules/Contents.php: -------------------------------------------------------------------------------- 1 | "コンテンツプラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"メインコンテンツの管理", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["t_log",0,1]] 10 | ]; 11 | public static function initModule(){ 12 | //MG::DB()->exec("drop table contents"); 13 | if(MG::DB()->isConnect() && !MG::DB()->isTable("contents")){ 14 | MG::DB()->exec( 15 | "create table contents( 16 | contents_id SERIAL primary key, 17 | contents_parent INTEGER references contents(contents_id), 18 | contents_priority INTEGER, 19 | contents_stat INTEGER,contents_type TEXT, 20 | contents_date timestamp with time zone,contents_update timestamp with time zone, 21 | contents_title_type integer,contents_title TEXT,contents_value TEXT)"); 22 | MG::DB()->exec("insert into contents values(default,null,1000,1,'PAGE',current_timestamp,current_timestamp,0,'Top','')"); 23 | Files::createDir(1,"Contents"); 24 | 25 | } 26 | } 27 | public static function JS_export($id=1){ 28 | if(!MG::isAdmin()) 29 | return false; 30 | $id = MG::getParam("id"); 31 | if($id == null) 32 | $id = 1; 33 | $values = MG::DB()->queryData( 34 | "select contents_id as id,contents_parent as pid,contents_stat as stat,contents_priority as priority,contents_type as type,to_char(contents_date at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as date,to_char(contents_update at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as update,contents_title_type as title_type,contents_title as title,contents_value as value from contents order by contents_type='PAGE',contents_priority" 35 | ); 36 | if ($values === null) 37 | return null; 38 | foreach ($values as &$value) { 39 | $id2 = $value["id"]; 40 | //ファイルデータの読み出し 41 | $path = Self::getDirPath($id2); 42 | $fileId = Files::getDirId(1, $path); 43 | if ($fileId != null) { 44 | $fileList = Files::getChildList($fileId); 45 | if(count($fileList)){ 46 | foreach($fileList as $fileId){ 47 | $value["files"][] = Files::getFile($fileId[0]); 48 | } 49 | } 50 | } 51 | //ID参照用データの作成 52 | $items[$id2] = &$value; 53 | } 54 | 55 | //親子関係の作成 56 | foreach ($items as &$item) { 57 | if ($item["pid"] !== null) { 58 | $parent = &$items[$item["pid"]]; 59 | $parent["childs"][] = &$item; 60 | } 61 | } 62 | ob_start("ob_gzhandler"); 63 | //header('content-type: application/force-download'); 64 | header('content-type: text/json'); 65 | header('Content-disposition: attachment; filename="export.json"'); 66 | header("Access-Control-Allow-Origin: *"); 67 | echo json_encode($items[$id], JSON_UNESCAPED_UNICODE); 68 | exit(0); 69 | } 70 | public static function JS_import($id,$mode,$value){ 71 | if($id == null) 72 | return false; 73 | $value = json_decode($value, true); 74 | MG::DB()->exec("begin"); 75 | if($mode == 0){ 76 | if($id == 1){ 77 | //全データを削除 78 | MG::DB()->exec("TRUNCATE table contents;select setval ('contents_contents_id_seq', 1, false);"); 79 | //関連ファイルの削除 80 | $fileId = Files::getDirId(1, "/Contents"); 81 | Files::deleteFile($fileId); 82 | Files::createDir(1, "Contents"); 83 | //インポート処理 84 | Self::import(null, $value); 85 | }else{ 86 | //上書き元のデータを取得 87 | $contents = MG::DB()->gets("select contents_parent as parent,contents_priority as priority from contents where contents_id=?",$id); 88 | $ids = []; 89 | //上書き元のデータを削除 90 | Self::deleteContents($id, $ids); 91 | $value["priority"] = $contents["priority"]; 92 | Self::import($contents["parent"],$value); 93 | } 94 | }else{ 95 | Self::import($id ,$value); 96 | } 97 | MG::DB()->exec("commit"); 98 | 99 | } 100 | public static function import($pid,$value){ 101 | //データの挿入 102 | $cid = MG::DB()->get( 103 | "insert into contents values(default,?,?,?,?,?,?,?,?,?) RETURNING contents_id", 104 | $pid, 105 | $value["priority"], 106 | $value["stat"], 107 | $value["type"], 108 | $value["date"], 109 | $value["update"], 110 | $value["title_type"], 111 | $value["title"], 112 | $value["value"] 113 | ); 114 | if($cid === null) 115 | return false; 116 | //ファイルの復元処理 117 | if(isset($value["files"])){ 118 | $ids = []; 119 | $dirId = Files::createDir(1, Self::getDirPath($cid)); 120 | foreach($value["files"] as $file){ 121 | $ids[$file["id"]] = Files::setFile($dirId, $file["name"],$file["date"],$file["value"]); 122 | } 123 | foreach($ids as $srcId => $destId){ 124 | $convertSrc[] = sprintf('/src="\?command=Files\.download&id=%d"/',$srcId); 125 | $convertDest[] = sprintf('src="?command=Files.download&id=%d"', $destId); 126 | } 127 | $value["value"] = preg_replace($convertSrc, $convertDest, $value["value"]); 128 | MG::DB()->exec( 129 | "update contents set contents_value=? where contents_id=?", 130 | $value["value"], 131 | $cid); 132 | } 133 | //子データの挿入 134 | if(isset($value["childs"])){ 135 | foreach($value["childs"] as $child){ 136 | Self::import($cid,$child); 137 | } 138 | } 139 | return true; 140 | } 141 | public static function JS_getTree($id=1){ 142 | //権限によって取得データに条件をつける 143 | $visible = MG::isAdmin()?"":"where contents_stat=1"; 144 | //ツリー構造に必要なデータを抽出 145 | $values = MG::DB()->queryData( 146 | "select contents_id as id,contents_parent as pid,contents_stat as stat, 147 | contents_type as type,contents_title as title from contents $visible order by contents_type='PAGE',contents_priority"); 148 | if($values === null) 149 | return null; 150 | //ID参照用データの作成 151 | foreach($values as &$value){ 152 | $items[$value["id"]] = &$value; 153 | } 154 | //親子関係の作成 155 | foreach($items as &$item){ 156 | if($item["pid"] !== null && isset($items[$item["pid"]])){ 157 | $parent = &$items[$item["pid"]]; 158 | $parent["childs"][] = &$item; 159 | } 160 | } 161 | //最上位のデータを返す 162 | return $items[$id]; 163 | } 164 | public static function JS_getContentsPage($id){ 165 | $pid = Self::getParentPage($id); 166 | if($pid == 0) 167 | return null; 168 | $contents = Self::JS_getContents($pid); 169 | if($contents === null) 170 | return null; 171 | $contents["childs"] = Self::getContentsPageFromParent($pid); 172 | 173 | $images = []; 174 | Self::getImages($contents, $images); 175 | foreach($images as $id){ 176 | header("link: ;rel=preload;as=image;",false); 177 | } 178 | 179 | return $contents; 180 | } 181 | public static function getImages($contents,&$images){ 182 | preg_match_all('/queryData("select contents_id as id,contents_parent as pid,contents_stat as stat,contents_type as type,to_char(contents_date at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as date,to_char(contents_update at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as update,contents_title_type as title_type,contents_title as title,contents_value as value from contents where contents_id=? $visible",$id); 193 | return $values[0]; 194 | } 195 | public static function JS_updateContents($id,$stat,$date,$contentsType,$titleType,$title,$value){ 196 | if (!MG::isAdmin()) 197 | return null; 198 | return MG::DB()->exec( 199 | "update contents SET contents_stat=?,contents_date=?,contents_type=?,contents_update=current_timestamp, 200 | contents_title_type=?,contents_title=?,contents_value=? where contents_id=?", 201 | $stat,$date,$contentsType,$titleType,$title,$value,$id)==1; 202 | } 203 | public static function JS_deleteContents($id){ 204 | if (!MG::isAdmin()) 205 | return null; 206 | $ids = []; 207 | MG::DB()->exec("begin"); 208 | $flag = Self::deleteContents($id,$ids); 209 | MG::DB()->exec("commit"); 210 | return $ids; 211 | } 212 | 213 | public static function JS_createContents($id,$vector,$type){ 214 | if (!MG::isAdmin()) 215 | return null; 216 | $cid = 0; 217 | switch($vector){ 218 | case 0: 219 | case 1: 220 | $pid = Self::getContentsParent($id); 221 | $priority = Self::getContentsPriority($id)+ ($vector == 0 ? -5 : 5); 222 | break; 223 | case 2: 224 | case 3: 225 | $pid = $id; 226 | $priority = $vector == 2 ? 0 : 100000; 227 | break; 228 | default: 229 | return null; 230 | 231 | } 232 | $titleType = 1; 233 | if ($type != 'PAGE') { 234 | $count = Self::getDeeps($pid); 235 | if ($count == 0) 236 | $titleType = 2; 237 | else 238 | $titleType = 3; 239 | } 240 | $cid = MG::DB()->get( 241 | "insert into contents values(default,?,?,-1,?, 242 | current_timestamp,current_timestamp,?,'New','') RETURNING contents_id", 243 | $pid, 244 | $priority, 245 | $type, 246 | $titleType); 247 | Self::updatePriority($pid); 248 | return ["pid"=>$pid,"id"=>$cid]; 249 | } 250 | public static function JS_moveVector($id,$vector) 251 | { 252 | if (!MG::isAdmin()) 253 | return null; 254 | $priority = Self::getContentsPriority($id); 255 | if(!$priority) 256 | return false; 257 | $count = MG::DB()->exec( 258 | "update contents set contents_priority = ? where contents_id=?", 259 | $priority +($vector<0?-15:15),$id); 260 | Self::updatePriorityFromChild($id); 261 | $priority2 = Self::getContentsPriority($id); 262 | return $priority !== $priority2; 263 | } 264 | public static function JS_checkUpdate($limit=10){ 265 | $pages = Self::getPages(); 266 | $pages = array_slice($pages,0,$limit); 267 | //不要データの削除 268 | foreach($pages as &$value){ 269 | unset($value["parent"]); 270 | unset($value["childs"]); 271 | } 272 | return $pages; 273 | } 274 | public static function getPages(){ 275 | //ツリー構造に必要なデータを抽出 276 | $values = MG::DB()->queryData( 277 | "select contents_id as id,contents_parent as pid,contents_stat as stat, 278 | to_char(contents_date at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as date, 279 | to_char(contents_update at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as update, 280 | contents_type as type,contents_title as title,contents_value as value from contents where contents_stat=1" 281 | ); 282 | if ($values === null) 283 | return null; 284 | //ID参照用データの作成 285 | foreach ($values as &$value) { 286 | $items[$value["id"]] = &$value; 287 | } 288 | //親子関係の作成 289 | foreach ($items as &$item) { 290 | if ($item["pid"] !== null && isset($items[$item["pid"]])) { 291 | $parent = &$items[$item["pid"]]; 292 | $parent["childs"][] = &$item; 293 | $item["parent"] = &$parent; 294 | } 295 | } 296 | 297 | $pages = []; 298 | foreach ($items as &$value) { 299 | if($value["type"] !== 'PAGE') 300 | continue; 301 | //作成日を調整 302 | $value["date"] = Self::getMaxDate($value); 303 | //タイトルの調整 304 | $title = $value["title"]; 305 | $p = $value; 306 | while(isset($p["parent"]) && $p = $p["parent"]){ 307 | if($p["id"] != 1) 308 | $title .= " ~ ". $p["title"]; 309 | } 310 | $value["title2"] = $title; 311 | $pages[] = $value; 312 | } 313 | 314 | //日付でソート 315 | usort($pages, function($a,$b){ 316 | return $a['date'] < $b['date']; 317 | }); 318 | 319 | return $pages; 320 | 321 | } 322 | private static function getMaxDate($value,$date=null){ 323 | if($date === null || ($value["type"] !== 'PAGE' && $value["date"] > $date)){ 324 | $date = $value["date"]; 325 | } 326 | if(isset($value["childs"])){ 327 | foreach($value["childs"] as $child){ 328 | if($child["type"] !== 'PAGE') 329 | $date = Self::getMaxDate($child,$date); 330 | } 331 | } 332 | return $date; 333 | } 334 | public static function JS_getRss() 335 | { 336 | $url = Params::getParam("Global_base_url", ""); 337 | $title = Params::getParam("Global_base_title", "タイトル"); 338 | $info = Params::getParam("Global_base_info", ""); 339 | 340 | header('Content-Type: text/xml; charset=utf-8', true); 341 | $rss = new SimpleXMLElement(''); 342 | $rss->addAttribute('version', '2.0'); 343 | $channel = $rss->addChild('channel'); 344 | 345 | $title = $channel->addChild('title', $title); 346 | $description = $channel->addChild('description', $info); 347 | $link = $channel->addChild('link', $url); 348 | $language = $channel->addChild('language', 'ja-jp'); 349 | 350 | $pages = Self::getPages(); 351 | 352 | foreach ($pages as $value) { 353 | $title2 = $value["title"]; 354 | $parent = $value; 355 | while(isset($parent["parent"]) && $parent = $parent["parent"]){ 356 | $title2 .= " ~ ". $parent["title"]; 357 | } 358 | 359 | $msg = strip_tags($value["value"]); 360 | $msg = str_replace(" ", " ", $msg); 361 | $msg = str_replace("&", "&", $msg); 362 | $item = $channel->addChild("item"); 363 | $item->addChild("title", $title2." ~ ".$title); 364 | $item->addChild('description', $msg); 365 | $item->addChild( 366 | "link", 367 | sprintf("%s?p=%d", $url, $value["id"]) 368 | ); 369 | 370 | $item->addChild("pubDate", date("r", strtotime($value["update"]))); 371 | } 372 | //ob_start("ob_gzhandler"); 373 | echo $rss->asXML(); 374 | exit(0); 375 | } 376 | 377 | public static function getContentsParent($id) 378 | { 379 | return MG::DB()->get("select contents_parent from contents where contents_id=?", $id); 380 | } 381 | public static function getContentsPriority($id) 382 | { 383 | return MG::DB()->get("select contents_priority from contents where contents_id=?", $id); 384 | } 385 | public static function updatePriority($id){ 386 | $values = MG::DB()->queryData2("select contents_id from contents where contents_parent=? order by contents_type='PAGE',contents_priority",$id); 387 | $sql = ""; 388 | foreach($values as $key => $value){ 389 | $sql .= sprintf("update contents SET contents_priority=%d where contents_id=%d;\n",($key+1)*1000,$value[0]); 390 | } 391 | if($sql !== "") 392 | MG::DB()->exec($sql); 393 | } 394 | public static function updatePriorityFromChild($id) 395 | { 396 | $values = MG::DB()->queryData2("select contents_id from contents where contents_parent=(select contents_parent from contents where contents_id=?) order by contents_type='PAGE',contents_priority", $id); 397 | $sql = ""; 398 | foreach ($values as $key => $value) { 399 | $sql .= sprintf("update contents SET contents_priority=%d where contents_id=%d;\n", ($key + 1) * 10, $value[0]); 400 | } 401 | if ($sql !== "") 402 | MG::DB()->exec($sql); 403 | } 404 | public static function deleteContents($id,&$idList){ 405 | $ids = MG::DB()->queryData2("select contents_id from contents where contents_parent=?",$id); 406 | foreach($ids as $cid) 407 | Self::deleteContents($cid[0], $idList); 408 | if($id === 1) 409 | return true; 410 | $idList[] = $id; 411 | //関連ファイルの削除 412 | $path = Self::getDirPath($id); 413 | $fileId = Files::getDirId(1, $path); 414 | Files::deleteFile($fileId); 415 | //コンテンツの削除 416 | return MG::DB()->exec("delete from contents where contents_id=?",$id)===1; 417 | } 418 | public static function &getContentsPageFromParent($pid) 419 | { 420 | $visible = MG::isAdmin() ? "" : "and contents_stat=1"; 421 | //親Idを元にコンテンツを抽出 422 | $values = MG::DB()->queryData("select contents_id as id,contents_parent as pid,contents_stat as stat,contents_type as type,to_char(contents_date at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as date,to_char(contents_update at time zone 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as update,contents_title_type as title_type,contents_title as title,contents_value as value from contents where contents_parent=? and contents_type != 'PAGE' $visible order by contents_priority", $pid); 423 | //子コンテンツを抽出 424 | foreach($values as &$value){ 425 | $value["childs"] = &Self::getContentsPageFromParent($value["id"]); 426 | } 427 | return $values; 428 | } 429 | public static function getDirPath($id){ 430 | return sprintf("/Contents/%04d/%02d", ((int)($id / 100)) * 100, $id % 100); 431 | } 432 | 433 | public static function getParentPage($id){ 434 | //PAGEタイプを持つ親を探す 435 | while(true){ 436 | $value = MG::DB()->gets("select contents_parent as pid,contents_type as type from contents where contents_id=?",$id); 437 | if($value === null) 438 | return 0; 439 | if($value['type'] === 'PAGE') 440 | break; 441 | $id = $value['pid']; 442 | } 443 | return $id; 444 | } 445 | public static function getParent($id){ 446 | return MG::DB()->get("select contents_parent from contents where contents_id = ?",$id); 447 | } 448 | public static function isParent($id,$checkId){ 449 | if($id === $checkId) 450 | return true; 451 | while($id = Self::getParent($id)){ 452 | if ($id === $checkId) 453 | return true; 454 | } 455 | return false; 456 | } 457 | public static function JS_moveContents($fromId,$toId){ 458 | //移動先が子だったら処理を行わない 459 | if(Self::isParent($toId,$fromId)) 460 | return false; 461 | //親の組み替え 462 | $flag = MG::DB()->exec("update contents set contents_parent=?,contents_priority=100000 where contents_id=?", $toId, $fromId) === 1; 463 | Self::updatePriority($toId); 464 | return $flag; 465 | } 466 | public static function getDeeps($id) 467 | { 468 | //PAGEタイプまでの深さを探索 469 | $count = 0; 470 | while (true) { 471 | $id = MG::DB()->get("select contents_parent as type from contents where contents_id=? and contents_type!='PAGE'", $id); 472 | if ($id === null) 473 | break; 474 | $count++; 475 | } 476 | return $count; 477 | } 478 | public static function getTitle(){ 479 | $id = MG::getParam("p"); 480 | if ($id == null) 481 | $id = 1; 482 | //指定されたコンテンツの情報を取得 483 | $contents = Self::JS_getContentsPage($id); 484 | $pid = $contents["pid"]; 485 | $parents[]=$contents; 486 | while(true){ 487 | $value = MG::DB()->gets("select contents_id as id,contents_parent as pid,contents_title as title from contents where contents_id=?",$pid); 488 | if(!$value) 489 | break; 490 | $pid = $value["pid"]; 491 | $parents[] = $value; 492 | } 493 | 494 | $title = htmlspecialchars(Params::getParam("Global_base_title", "")); 495 | foreach (array_reverse($parents) as $parent){ 496 | $title = htmlspecialchars($parent["title"]) . " ~ " . $title; 497 | } 498 | return $title; 499 | } 500 | public static function getCanonical(){ 501 | $id = MG::getParam("p"); 502 | if ($id == null) 503 | $id = 1; 504 | 505 | //指定されたコンテンツの情報を取得 506 | $contents = Self::JS_getContentsPage($id); 507 | if ($contents === null) 508 | return ''; 509 | $url = Params::getParam("Global_base_url", ""); 510 | return sprintf('',$url,$id); 511 | } 512 | public static function getBreadcrumb(){ 513 | $id = MG::getParam("p"); 514 | if ($id == null) 515 | $id = 1; 516 | 517 | //指定されたコンテンツの情報を取得 518 | $contents = Self::JS_getContentsPage($id); 519 | if ($contents === null) 520 | return ''; 521 | 522 | $parents[] = $contents; 523 | $pid = $contents["pid"]; 524 | while (true) { 525 | $value = MG::DB()->gets("select contents_id as id,contents_parent as pid,contents_title as title from contents where contents_id=?", $pid); 526 | if (!$value) 527 | break; 528 | $pid = $value["pid"]; 529 | $parents[] = $value; 530 | } 531 | $breadcrumb = [ 532 | "@context" => "http://schema.org", 533 | "@type" => "BreadcrumbList" 534 | ]; 535 | 536 | $list = []; 537 | $i=1; 538 | foreach (array_reverse($parents) as $parent) { 539 | $list[] = [ 540 | "@type" => "ListItem", 541 | "position" => $i++, 542 | "item" => 543 | [ 544 | "@id" => "?p=".$parent["id"], 545 | "name" => $parent["title"] 546 | ] 547 | ]; 548 | } 549 | $breadcrumb["itemListElement"] = $list; 550 | return sprintf('',json_encode($breadcrumb)); 551 | } 552 | public static function outputPage(){ 553 | $id = MG::getParam("p"); 554 | if($id == null) 555 | $id = 1; 556 | 557 | $contents = Self::JS_getContentsPage($id); 558 | if($contents === null) 559 | return; 560 | 561 | $strAdSense = ""; 562 | $adsense = Params::getParam("Global_base_adsense", ""); 563 | if($adsense!=""){ 564 | $strAdSense = sprintf( 565 | "\t\n". 566 | "\t\n", 572 | $adsense); 573 | } 574 | 575 | $parents[] = $contents; 576 | $pid = $contents["pid"]; 577 | while(true){ 578 | $value = MG::DB()->gets("select contents_id as id,contents_parent as pid,contents_title as title from contents where contents_id=?",$pid); 579 | if(!$value) 580 | break; 581 | $pid = $value["pid"]; 582 | $parents[] = $value; 583 | } 584 | 585 | $title = htmlspecialchars(Params::getParam("Global_base_title", "")); 586 | foreach (array_reverse($parents) as $parent){ 587 | $title = htmlspecialchars($parent["title"]) . " ~ " . $title; 588 | } 589 | $url = Params::getParam("Global_base_url", ""); 590 | $body = Self::outputContents($contents); 591 | printf( 592 | "\n\n\t\n\t\n" . 593 | "\t\n". 594 | "\t\n". 595 | "\t\n" . 596 | "\t%s\n" . 597 | "\t\n" . 598 | "%s". 599 | "\n\n", 600 | $url,$id, 601 | $title,htmlspecialchars(mb_substr(preg_replace('/\n|\r|\r\n/', '', strip_tags($body)), 0, 80)), 602 | $strAdSense 603 | ); 604 | //パンくずリスト 605 | echo "
    \n"; 606 | foreach(array_reverse($parents) as $parent){ 607 | printf( 608 | "\t
  • \n". 609 | "\t\t\n". 610 | "\t\t\t%s\n\t\t\n\t
  • \n", 611 | $parent["id"], 612 | htmlspecialchars($parent["title"])); 613 | } 614 | echo "
\n\n"; 615 | 616 | 617 | echo "$body\n\n\n"; 618 | } 619 | public static function outputContents($contens){ 620 | //タイトルの出力 621 | switch($contens["title_type"]){ 622 | case 1: 623 | $body = sprintf("

%s

\n", $contens["title"]); 624 | break; 625 | case 2: 626 | $body = sprintf("

%s

\n", $contens["title"]); 627 | break; 628 | case 3: 629 | $body = sprintf("

%s

\n", $contens["title"]); 630 | break; 631 | } 632 | $body .= sprintf("
%s
\n

%s

\n", date("Y-m-d H:i:s", strtotime($contens["date"])), $contens["value"]); 633 | 634 | foreach($contens["childs"] as $child){ 635 | $body .= Self::outputContents($child); 636 | } 637 | return $body; 638 | } 639 | 640 | } -------------------------------------------------------------------------------- /PHP/Modules/Files.php: -------------------------------------------------------------------------------- 1 | "ファイルプラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"ファイルデータの管理", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["t_log",0,1]] 10 | ]; 11 | public static function initModule(){ 12 | if(MG::DB()->isConnect() && !MG::DB()->isTable("files")){ 13 | MG::DB()->exec("create table files(files_id SERIAL PRIMARY KEY,files_parent INTEGER references files(files_id),files_kind INTEGER,users_id INTEGER references users(users_id),files_name TEXT,files_date TIMESTAMP with time zone,files_byte BYTEA);"); 14 | MG::DB()->exec("insert into files values(default,null,0,null,'[ROOT]',now(),null)"); 15 | } 16 | 17 | } 18 | public static function JS_createDir($parent,$name){ 19 | if(!MG::isAdmin()) 20 | return ["result"=>0,"message"=>"ディレクトリ作成 権限エラー"]; 21 | $id = Self::createDir($parent,$name); 22 | if($id === 0) 23 | return ["result" => 0, "message" => "フォルダの作成失敗"]; 24 | return ["result" => 1, "message" => "フォルダの作成", "value" => $id]; 25 | } 26 | public static function JS_setFileName($id,$name){ 27 | if(!MG::isAdmin()) 28 | return ["result"=>0,"message"=>"ファイル名変更 権限エラー"]; 29 | return Self::setFileName($id,$name); 30 | } 31 | public static function JS_deleteFiles($ids){ 32 | if(!MG::isAdmin()) 33 | return ["result"=>0,"message"=>"ファイル削除 権限エラー"]; 34 | return Self::deleteFiles($ids); 35 | } 36 | public static function JS_deleteFile($id){ 37 | if(!MG::isAdmin()) 38 | return ["result"=>0,"message"=>"ファイル削除 権限エラー"]; 39 | return Self::deleteFile($id); 40 | } 41 | public static function JS_getFileList($pid){ 42 | if(!MG::isAdmin()) 43 | return ["result"=>0,"message"=>"ファイルリスト取得 権限エラー"]; 44 | return Self::getFileList($pid); 45 | } 46 | public static function JS_getDirList(){ 47 | if(!MG::isAdmin()) 48 | return ["result"=>0,"message"=>"ディレクトリリスト取得 権限エラー"]; 49 | return Self::getDirList(); 50 | } 51 | public static function JS_getDirId($parent,$name){ 52 | if(!MG::isAdmin()) 53 | return ["result"=>0,"message"=>"ディレクトリリスト取得 権限エラー"]; 54 | $id = Self::getDirId(MG::getParam("parent"),MG::getParam("name")); 55 | if($id === null) 56 | return ["result"=>0,"message"=>"フォルダID取得 エラー"]; 57 | else 58 | return ["result"=>1,"message"=>"フォルダID取得","id"=>$id]; 59 | } 60 | public static function JS_uploadFile($parent,$name){ 61 | if(!MG::isAdmin()) 62 | return ["result"=>0,"message"=>"ファイルアップロード 権限エラー"]; 63 | if(MG::getUserCode() === null) 64 | $result = ["result"=>0,"message"=>"ファイルアップロード 権限エラー"]; 65 | else if(!isset($_SERVER['CONTENT_LENGTH'])) 66 | $result = ["result"=>0,"message"=>"ファイルアップロード パラメータエラー"]; 67 | else{ 68 | $file = fopen("php://input", "r"); 69 | $result = Self::saveFile($parent,$name,$file,$_SERVER['CONTENT_LENGTH']); 70 | fclose($file); 71 | } 72 | return $result; 73 | } 74 | public static function JS_download(){ 75 | if(MG::isParams(["id"])) 76 | Self::getFileStream(MG::getParam("id")); 77 | return null; 78 | } 79 | public static function getFileInfo($fileId){ 80 | return MG::DB()->gets("select files_name,files_kind,octet_length(files_byte),files_date from files where files_id=?",$fileId); 81 | } 82 | public static function getFile($fileId) 83 | { 84 | return MG::DB()->gets("select files_id as id,files_kind as kind,files_name as name,octet_length(files_byte) as size,files_date as date,encode(files_byte, 'base64') as value from files where files_id=? and files_kind=1", $fileId); 85 | } 86 | public static function setFile($pid,$name,$date,$value){ 87 | return MG::DB()->get( 88 | "insert into files values(default,?,1,?,?,?,decode(?,'base64')) returning files_id", 89 | $pid,MG::getUserCode(),$name,$date,$value); 90 | } 91 | public static function getFileStream($fileId){ 92 | $stmt = MG::DB()->query("select files_name,octet_length(files_byte),files_date,files_byte from files where files_id=? and files_kind=1",$fileId); 93 | $stmt->bindColumn(1, $name, PDO::PARAM_STR); 94 | $stmt->bindColumn(2, $size, PDO::PARAM_INT); 95 | $stmt->bindColumn(3, $date, PDO::PARAM_STR); 96 | $stmt->bindColumn(4, $fp, PDO::PARAM_LOB); 97 | 98 | if($stmt->fetch() === false) 99 | return; 100 | $httpDisposition= "inline;"; 101 | $contentType = "application/octet-stream"; 102 | $ext = substr($name, strrpos($name, '.') + 1); 103 | switch(strtolower($ext)){ 104 | case "png": 105 | $contentType = "image/png"; 106 | break; 107 | case "svg": 108 | $contentType = "image/svg+xml"; 109 | break; 110 | case "jpeg": 111 | case "jpg": 112 | $contentType = "image/jpeg"; 113 | break; 114 | case "gif": 115 | $contentType = "image/gif"; 116 | break; 117 | default: 118 | $httpDisposition= "attachment;"; 119 | break; 120 | } 121 | header("content-length: " . $size); 122 | header("Last-Modified: ". date("r", strtotime($date))); 123 | header("Content-type: $contentType"); 124 | header("Content-Disposition: $httpDisposition filename*=utf-8'jp'".urlencode($name)); 125 | fpassthru($fp); 126 | exit(0); 127 | 128 | } 129 | public static function getDirList(){ 130 | $values = MG::DB()->queryData("select files_id,files_parent,files_kind,files_name,files_date,octet_length(files_byte) as size 131 | from files where files_kind=0 order by files_name"); 132 | $hash = []; 133 | if($values!==null){ 134 | foreach($values as &$value){ 135 | $id = $value["files_id"]; 136 | $hash[$id] = [ 137 | "id"=>$value["files_id"], 138 | "parent"=>$value["files_parent"], 139 | "kind"=>$value["files_kind"], 140 | "name"=>$value["files_name"], 141 | "size"=>$value["size"], 142 | "files_date"=>null, 143 | "childs"=>[]]; 144 | } 145 | foreach($hash as $id=>&$file){ 146 | $parent = $file["parent"]; 147 | if($parent > 0) 148 | $hash[$parent]["childs"][] = &$file; 149 | } 150 | $result = ["result"=>1,"message"=>"フォルダリストの取得","value"=>$hash[1]]; 151 | } 152 | else 153 | $result = ["result"=>0,"message"=>"フォルダリストの取得 エラー"]; 154 | return $result; 155 | } 156 | public static function getFileList($parentId){ 157 | date_default_timezone_set("UTC"); 158 | $values = MG::DB()->queryData( 159 | "select files_id,files_parent,files_kind,files_name,files_date,octet_length(files_byte) as size 160 | from files where files_parent=? order by files_kind,files_name",$parentId); 161 | $files = []; 162 | if($values!==null){ 163 | foreach($values as &$value){ 164 | $files[] = [ 165 | "id"=>$value["files_id"], 166 | "parent"=>$value["files_parent"], 167 | "kind"=>$value["files_kind"], 168 | "name"=>$value["files_name"], 169 | "date"=>date("Y-m-d\TH:i:s\Z", strtotime($value["files_date"])), 170 | "size"=>$value["size"], 171 | "files_date"=>null, 172 | "childs"=>[]]; 173 | } 174 | $result = ["result"=>1,"message"=>"ファイルリストの取得","values"=>$files]; 175 | } 176 | else 177 | $result = ["result"=>0,"message"=>"ファイルリストの取得 エラー"]; 178 | return $result; 179 | } 180 | public static function getChildList($fileId){ 181 | $sql = sprintf("select files_id from files where files_parent=%d",$fileId); 182 | $values = MG::DB()->queryData2($sql); 183 | return $values; 184 | } 185 | public static function getFileId($parentId,$name){ 186 | //フォルダを分解 187 | $values = explode("/",$name); 188 | $p = $parentId; 189 | $count = count($values); 190 | for($i=0;$i<$count;$i++){ 191 | $name2 = $values[$i]; 192 | $id = MG::DB()->get("select files_id from files where files_parent=? and files_name=?", 193 | $p,$name2); 194 | if($id === null) 195 | return null; 196 | $p = $id; 197 | } 198 | return $id; 199 | } 200 | public static function setFileName($fileId,$name){ 201 | if(MG::DB()->exec("update files set files_name=? where files_id=?",$name,$fileId)>0){ 202 | return ["result"=>1,"message"=>"ファイル名の変更"]; 203 | } 204 | return ["result"=>0,"message"=>"ファイル名の変更 失敗"]; 205 | } 206 | 207 | public static function saveFile($parentId,$name,$file,$size){ 208 | $id = Self::getFileId(MG::getParam("parent"),MG::getParam("name")); 209 | if($id === null){ 210 | $row = MG::DB()->gets2("insert into files values(default,?,1,?,?,now(),?) returning files_id,octet_length(files_byte)", 211 | $parentId,MG::getUserCode(),$name,$file); 212 | }else{ 213 | $row = MG::DB()->gets2("update files set files_byte=?,user_data_id=?,files_date=now() where files_id=? returning files_id,octet_length(files_byte)", 214 | $file,MG::getUserCode(),$id); 215 | } 216 | 217 | if($row[0] < 1 || $row[1] != $size){ 218 | Self::deleteFile($row[0]); 219 | return ["result"=>0,"message"=>"ファイルアップロード エラー"]; 220 | } 221 | return ["result"=>1,"message"=>"ファイルアップロード","value"=>$row[0]]; 222 | } 223 | public static function deleteFiles($files){ 224 | foreach($files as $fileId){ 225 | $result = Self::deleteFile($fileId); 226 | if($result["result"] == 0) 227 | break; 228 | } 229 | return $result; 230 | } 231 | public static function deleteFile($fileId){ 232 | $fileId = (int)$fileId; 233 | if($fileId > 1){ 234 | //配下のオブジェクトを削除 235 | $childs = Self::getChildList($fileId); 236 | foreach($childs as $child){ 237 | Self::deleteFile($child[0]); 238 | } 239 | //ファイル削除 240 | $sql = sprintf("delete from files where files_id=%d", 241 | $fileId); 242 | if(MG::DB()->exec($sql) > 0){ 243 | return ["result"=>1,"message"=>"ファイル削除"]; 244 | } 245 | } 246 | return ["result"=>0,"message"=>"ファイル削除 失敗"]; 247 | } 248 | public static function createDir($parentId,$name){ 249 | //フォルダを分解 250 | $values = explode("/",ltrim($name, '/')); 251 | 252 | $p = $parentId; 253 | for($i=0;$iget( 270 | "insert into files values(default,?,0,?,?,now(),null) returning files_id", 271 | $p,MG::getUserCode(),$name2); 272 | if($id === null) 273 | $result = 0; 274 | $p = $id; 275 | } 276 | return $id; 277 | } 278 | public static function getDirId($parent,$name){ 279 | $values = explode("/",ltrim($name, '/')); 280 | $id = 1; 281 | foreach($values as $value){ 282 | $id = MG::DB()->get("select files_id from files where files_parent=? and files_name=?", 283 | $id,$value); 284 | if($id === null) 285 | return null; 286 | } 287 | return $id; 288 | } 289 | 290 | } -------------------------------------------------------------------------------- /PHP/Modules/GParams.php: -------------------------------------------------------------------------------- 1 | "パラメータプラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"グローバルパラメータの保存", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["params",0,1]] 10 | ]; 11 | public static function initModule(){ 12 | if (MG::DB()->isConnect()) 13 | MG::DB()->exec("create table IF NOT EXISTS params(params_name TEXT primary key,params_value TEXT);"); 14 | } 15 | public static function JS_setParam($name,$value) 16 | { 17 | if (!MG::DB()->isConnect()) 18 | return null; 19 | return Self::setParam("Global_" . $name,$value); 20 | } 21 | public static function JS_getParam($name) 22 | { 23 | if (!MG::DB()->isConnect()) 24 | return null; 25 | return Self::getParam("Global_" . $name); 26 | } 27 | public static function JS_getParams($names) 28 | { 29 | if (!MG::DB()->isConnect()) 30 | return null; 31 | $names2 = []; 32 | foreach ($names as $name) { 33 | $names2[] = "Global_" . $name; 34 | } 35 | $params = Self::getParams(...$names2); 36 | $params2 = []; 37 | foreach ($params as $key => $value) { 38 | $params2[substr($key,7)] = $value; 39 | } 40 | return $params2; 41 | } 42 | public static function getParam($name,$default=null){ 43 | $ret = MG::DB()->get("select params_value from params where params_name=?",$name); 44 | return $ret!==null?$ret:$default; 45 | } 46 | public static function setParam($name,$value){ 47 | if (!MG::isAdmin()) 48 | return false; 49 | if(MG::DB()->exec("update params set params_value=? where params_name=?",$value,$name)==0){ 50 | return MG::DB()->exec("insert into params values(?,?)",$name,$value) == 1; 51 | } 52 | return true; 53 | } 54 | public static function &getParams(...$names){ 55 | $s = MG::DB()->createValueParam($names); 56 | $sql = sprintf("select params_name,params_value from params where params_name in (%s)",$s); 57 | $values = MG::DB()->queryData2($sql); 58 | $params = []; 59 | foreach($values as &$value){ 60 | $params[$value[0]] = $value[1]; 61 | } 62 | foreach($names as $name){ 63 | if(!isset($params[$name])) 64 | $params[$name] = null; 65 | } 66 | return $params; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /PHP/Modules/Log.php: -------------------------------------------------------------------------------- 1 | "ログプラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"ログデータの管理", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["t_log",0,1]] 10 | ]; 11 | 12 | public static function initModule(){ 13 | if(MG::LDB()->isConnect()) 14 | MG::LDB()->exec("create table IF NOT EXISTS t_log(id integer primary key,log_time timestamp, 15 | ip text,user_id text,user_name text,command text,message text)"); 16 | } 17 | 18 | public static function output($command,$message){ 19 | if(!MG::LDB()->isConnect()) 20 | return; 21 | $user = MG::getSession(); 22 | if($user !== null){ 23 | MG::LDB()->exec("insert into t_log values(null,current_timestamp,?,?,?,?,?)", 24 | $_SERVER["REMOTE_ADDR"],$user['users_id']!==null?$user['users_id']:'', 25 | $user['users_name']!==null?$user['users_name']:'', 26 | $command,$message); 27 | 28 | } 29 | } 30 | public static function JS_getLog($count){ 31 | if(MG::isAdmin()) 32 | return MG::LDB()->queryData2("select * from t_log order by id desc limit ?",$count); 33 | else{ 34 | $user = MG::getSession(); 35 | if($user===null || $user['users_id']===null) 36 | return []; 37 | return MG::LDB()->queryData2("select * from t_log where user_id=? order by id desc limit ?",$user['user_id'],$count); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /PHP/Modules/Params.php: -------------------------------------------------------------------------------- 1 | "パラメータプラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"パラメータの保存", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["params",0,1]] 10 | ]; 11 | public static function initModule(){ 12 | MG::LDB()->exec("create table IF NOT EXISTS params(params_name TEXT primary key,params_value TEXT);"); 13 | } 14 | public static function JS_setParam($name,$value) 15 | { 16 | return Params::setParam("Global_" . $name,$value); 17 | } 18 | public static function JS_getParam($name) 19 | { 20 | return Params::getParam("Global_" . $name); 21 | } 22 | public static function JS_getParams($names) 23 | { 24 | $names2 = []; 25 | foreach ($names as $name) { 26 | $names2[] = "Global_" . $name; 27 | } 28 | $params = Params::getParams(...$names2); 29 | $params2 = []; 30 | foreach ($params as $key => $value) { 31 | $params2[substr($key,7)] = $value; 32 | } 33 | return $params2; 34 | } 35 | public static function getParam($name,$default=null){ 36 | $ret = MG::LDB()->get("select params_value from params where params_name=?",$name); 37 | return $ret!==null?$ret:$default; 38 | } 39 | public static function setParam($name,$value){ 40 | if(MG::LDB()->exec("update params set params_value=? where params_name=?",$value,$name)==0){ 41 | return MG::LDB()->exec("insert into params values(?,?)",$name,$value) == 1; 42 | } 43 | return true; 44 | } 45 | public static function &getParams(...$names){ 46 | $s = MG::LDB()->createValueParam($names); 47 | $sql = sprintf("select params_name,params_value from params where params_name in (%s)",$s); 48 | $values = MG::LDB()->queryData2($sql); 49 | $params = []; 50 | foreach($values as &$value){ 51 | $params[$value[0]] = $value[1]; 52 | } 53 | foreach($names as $name){ 54 | if(!isset($params[$name])) 55 | $params[$name] = null; 56 | } 57 | return $params; 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /PHP/Modules/Session.php: -------------------------------------------------------------------------------- 1 | "セッションプラグイン", 5 | "VERSION"=>1.00, 6 | "DESCRIPTION"=>"セッションを管理する", 7 | "AUTHOR"=>"SoraKumo", 8 | "TABLES"=>[["session",0,1],["users",0,1]] 9 | ]; 10 | 11 | static $JS_ENABLE; 12 | static $mSessionValues; 13 | public static function initModule(){ 14 | MG::LDB()->exec( 15 | "create table IF NOT EXISTS session(session_hash text primary key,users_id text,users_name text,users_info text,login_time timestamp); 16 | create table IF NOT EXISTS users(users_id integer primary key,users_name text unique,users_password text)"); 17 | } 18 | public static function JS_requestLogin($id,$pass){ 19 | if(!Self::login($id,$pass)) 20 | return ["result"=>0,"message"=>"ログイン 失敗"]; 21 | return Self::JS_requestSession(); 22 | } 23 | public static function isLocalAdmin($id=null,$pass=null){ 24 | if($id === null) 25 | return MG::LDB()->get("select 1 from users limit 1") == 1; 26 | $p = MG::LDB()->get("select users_password from users where users_name=?",$id); 27 | if($p === null) 28 | return false; 29 | return MD5(MG::getSessionHash().$p) === $pass; 30 | } 31 | public static function JS_createAdmin($id,$pass){ 32 | if(!Self::isLocalAdmin()){ 33 | $pass = md5($pass); 34 | if(MG::LDB()->exec("insert into users values(null,?,?)",$id,$pass) == 1){ 35 | Self::login($id,md5(MG::getSessionHash().$pass)); 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | public static function isDBParams(){ 42 | $params = Self::getParams("DATABASE_URL","DATABASE_ID","DATABASE_PASS","DATABASE_NAME"); 43 | $count = 0; 44 | foreach($params as $p){ 45 | if($p !== null) 46 | $count++; 47 | } 48 | return $count===4; 49 | } 50 | public static function JS_requestSession(){ 51 | //ローカルDBチェック 52 | if(!MG::LDB()->isConnect()) 53 | return ["result"=>-1,"sessionHash"=>MG::getSessionHash(),"message"=>"ローカルデータベースに接続できない"]; 54 | 55 | //セッション情報の読み取り 56 | $values = Self::getSessionValues(); 57 | //セッションハッシュが無ければ作成 58 | if($values === null){ 59 | MG::setSessionHash(Self::createHash()); 60 | $values = Self::getSessionValues(); 61 | } 62 | 63 | //ローカル管理者 64 | if(!Self::isLocalAdmin()){ 65 | return ["result"=>-2,"sessionHash"=>MG::getSessionHash(),"message"=>"ローカル管理者が設定されていない"]; 66 | } 67 | 68 | if($values !== null && $values["users_id"]!==null){ 69 | //ローカル管理者だった場合の処理 70 | if($values["users_id"] == -1){ 71 | return ["result"=>1,"message"=>"セッション取得", 72 | "sessionHash"=>MG::getSessionHash(), 73 | "user"=>[ 74 | "id"=>$values['users_id'], 75 | "name"=>$values['users_name'], 76 | "info"=>$values['users_info'], 77 | "groups"=>["SYSTEM_ADMIN"]]]; 78 | } 79 | //通常ユーザ 80 | return ["result"=>1,"message"=>"セッション取得", 81 | "sessionHash"=>MG::getSessionHash(), 82 | "user"=>[ 83 | "id"=>$values['users_id'], 84 | "name"=>$values['users_name'], 85 | "info"=>$values['users_info'], 86 | "groups"=>$values['groups']]]; 87 | } 88 | 89 | //セッションユーザが空の場合の処理はGUEST情報を返す 90 | if($values === null || $values['users_id'] === null){ 91 | return ["result"=>1,"message"=>"セッション取得", 92 | "sessionHash"=>MG::getSessionHash(), 93 | "user"=>[ 94 | "id"=>'0', 95 | "name"=>'GUEST', 96 | "info"=>'', 97 | "groups"=>[]]]; 98 | } 99 | 100 | if(Self::DB()->isConnect()){ 101 | } 102 | 103 | 104 | //セッション情報の取得 105 | $session = Self::getValues(); 106 | if($session === null){ 107 | //セッションが無かったら作成する 108 | MG::setSessionHash(Self::createHash()); 109 | $session = ['users_id'=>0,'users_name'=>'GUEST','users_info'=>'']; 110 | } 111 | //セッション情報の生成 112 | $result = ["result"=>1,"message"=>"セッション取得", 113 | "sessionHash"=>MG::getSessionHash(), 114 | "user"=>[ 115 | "id"=>$session['users_id'], 116 | "name"=>$session['users_name'], 117 | "info"=>$session['users_info']], 118 | "groups"=>[UserGroup::getUserGroupNames($session['users_id'])] 119 | ]; 120 | return $result; 121 | } 122 | 123 | public static function createHash(){ 124 | while(true){ 125 | $sessionHash = md5(time()); 126 | if(!Self::isSession($sessionHash)) 127 | break; 128 | sleep(0); 129 | } 130 | MG::LDB()->exec("delete from session where login_time < current_timestamp + '-1 hour'"); 131 | MG::LDB()->exec("insert into session values(?,null,null,null,current_timestamp)",$sessionHash); 132 | return $sessionHash; 133 | } 134 | public static function isSession(){ 135 | $stmt = MG::LDB()->query("select users_id from session where session_hash=? limit 1",MG::getSessionHash()); 136 | if($stmt === false){ 137 | return false; 138 | } 139 | if($row = $stmt->fetch(PDO::FETCH_NUM)){ 140 | return true; 141 | } 142 | return false; 143 | } 144 | public static function login($id,$pass){ 145 | //ローカル管理者かチェック 146 | if(Self::isLocalAdmin($id,$pass)){ 147 | $count = MG::LDB()->exec("update session set users_id=?,users_name=?,users_info=? where session_hash=?", 148 | -1,$id,'',MG::getSessionHash()); 149 | return $count>0; 150 | } 151 | //メインDBに接続できなければ終了 152 | if(!MG::DB()->isConnect()) 153 | return false; 154 | 155 | $row = MG::DB()->gets("select * from users where users_mail=? and md5(?||users_password)=?", 156 | $id,MG::getSessionHash(),$pass); 157 | if($row === null) 158 | return false; 159 | 160 | $count = MG::LDB()->exec("update session set users_id=?,users_name=?,users_info=? where session_hash=?", 161 | $id,$row['users_name'],'',MG::getSessionHash()); 162 | return $count > 0; 163 | } 164 | //セッションハッシュから情報を返す 165 | public static function getSession($sessionHash){ 166 | return MG::LDB()->gets("select users_id,users_name,users_info from session where session_hash=? limit 1", 167 | $sessionHash); 168 | } 169 | 170 | public static function getSessionValues(){ 171 | if(Self::$mSessionValues == null){ 172 | $session = Self::getSession(MG::getSessionHash());; 173 | if($session !== null){ 174 | if($session["users_id"] == -1) 175 | $session['groups'] = ['SYSTEM_ADMIN']; 176 | else 177 | $session['groups'] = MG::getUserGroups($session["users_id"]); 178 | Self::$mSessionValues = $session; 179 | } 180 | } 181 | return Self::$mSessionValues; 182 | } 183 | public static function getSessionValue($index){ 184 | return Self::getValues()[$index]; 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /PHP/Modules/Users.php: -------------------------------------------------------------------------------- 1 | "ユーザ管理プラグイン", 6 | "VERSION"=>1.00, 7 | "DESCRIPTION"=>"ユーザ情報の管理を行う", 8 | "AUTHOR"=>"SoraKumo", 9 | "TABLES"=>[["users",1,1]] 10 | ]; 11 | public static function initModule(){ 12 | if(MG::DB()->isConnect() && !MG::DB()->isTable("users")){ 13 | MG::DB()->exec( 14 | "create table IF NOT EXISTS users(users_id SERIAL PRIMARY KEY,users_enable BOOLEAN, 15 | users_mail TEXT,users_password TEXT,users_name TEXT,users_info TEXT,UNIQUE(users_mail)); 16 | create table user_group(user_group_id SERIAL PRIMARY KEY,user_group_enable boolean,user_group_name TEXT,user_group_info TEXT); 17 | insert into user_group values(default,true,'SYSTEM_ADMIN','管理者グループ'); 18 | insert into user_group values(default,true,'GUEST','ゲストグループ'); 19 | create table user_group_bind(users_id INTEGER references users(users_id), 20 | user_group_id INTEGER references user_group(user_group_id), 21 | user_group_bind_value INTEGER,PRIMARY KEY(users_id,user_group_id));"); 22 | } 23 | } 24 | public static function getUserCount(){ 25 | return MG::DB()->get("select count(*) from users"); 26 | } 27 | public static function getUsers(){ 28 | return MG::DB()->queryData("select * from users order by users_id"); 29 | } 30 | public static function getUserIdFromMail($mail){ 31 | return MG::DB()->get("select users_id from users where users_mail=?",$mail); 32 | } 33 | public static function addUser(){ 34 | return MG::DB()->get("insert into users values(default,true,null,null,'新規ユーザ','') returning users_id"); 35 | } 36 | public static function delUser($id){ 37 | return MG::DB()->exec("delete from users where users_id=?",$id); 38 | } 39 | public static function setUser($id,$enable,$name,$mail,$pass,$info){ 40 | $keys = ["users_id"]; 41 | $values = ["users_id"=>$id]; 42 | if($enable !== null) $values["users_enable"] = $enable; 43 | if($name !== null) $values["users_name"] = $name; 44 | if($mail !== null) $values["users_mail"] = $mail; 45 | if($pass !== null) $values["users_password"] = $pass; 46 | if($info !== null) $values["users_info"] = $info; 47 | return MG::DB()->replace("users",$keys,$values); 48 | } 49 | public static function getGroupNames($userId){ 50 | if(!MG::DB()->isConnect()) 51 | return null; 52 | $values = MG::DB()->queryData2("select user_group_name from user_group where user_group_id in ". 53 | "(select user_group_id from user_group_bind where users_id = (select users_id from users where users_mail=?))", 54 | $userId); 55 | if(!$values) 56 | return null; 57 | $result = []; 58 | foreach($values as $value) 59 | $result[] = $value[0]; 60 | return $result; 61 | } 62 | public static function getGroups($userId){ 63 | return MG::DB()->queryData("select * from user_group where user_group_id in ". 64 | "(select user_group_id from user_group_bind where users_id=?)", 65 | $userId); 66 | } 67 | public static function getGroupUserCount($groupName){ 68 | if($groupName === null) 69 | return MG::DB()->get("select count(*) from user_group_bind"); 70 | else 71 | return MG::DB()->get( 72 | "select count(*) from user_group_bind where user_group_id in ". 73 | "(select user_group_id from user_group where user_group_name=?)", 74 | $groupName); 75 | } 76 | public static function JS_getUsers(){ 77 | if(!MG::isAdmin()) 78 | return false; 79 | return Self::getUsers(); 80 | } 81 | public static function JS_addUser(){ 82 | if(!MG::isAdmin()) 83 | return false; 84 | return Self::addUser(); 85 | } 86 | public static function JS_delUser($userId){ 87 | if(!MG::isAdmin()) 88 | return false; 89 | return Self::delUser($userId); 90 | } 91 | public static function JS_setUser($id,$enable=null,$name=null,$mail=null,$pass=null,$info=null){ 92 | if(!MG::isAdmin()) 93 | return ["result"=>0,"message"=>"ユーザーデータの設定 権限エラー"]; 94 | Self::setUser($id,$enable,$name,$mail,$pass,$info); 95 | $result = ["result"=>1,"message"=>"ユーザーデータの設定"]; 96 | return $result; 97 | } 98 | public static function JS_getGroups(){ 99 | if(!MG::isAdmin()) 100 | return false; 101 | return MG::DB()->queryData("select *,0 from user_group order by user_group_id"); 102 | } 103 | public static function JS_setGroup($id,$enable,$name,$info){ 104 | if(!MG::isAdmin()) 105 | return false; 106 | 107 | $keys = ["user_group_id"]; 108 | $values = ["user_group_id"=>$id]; 109 | if($enable !== null) 110 | $values["user_group_enable"] = $enable; 111 | if($name !== null) 112 | $values["user_group_name"] = $name; 113 | if($info !== null) 114 | $values["user_group_info"] = $info; 115 | return MG::DB()->replace("user_group",$keys,$values); 116 | } 117 | public static function JS_delGroup($id){ 118 | if(!MG::isAdmin()) 119 | return false; 120 | return MG::DB()->exec("delete from user_group where user_group_id=?",$id); 121 | } 122 | public static function JS_addGroup(){ 123 | if(!MG::isAdmin()) 124 | return false; 125 | return MG::DB()->get("insert into user_group values(default,true,'新規グループ','') returning user_group_id"); 126 | } 127 | public static function JS_addGroupUser($groupId,$userId){ 128 | if(!MG::isAdmin()) 129 | return false; 130 | return MG::DB()->exec("insert into user_group_bind values(?,?)",$userId,$groupId) === 1; 131 | } 132 | public static function JS_delGroupUser($groupId,$userId){ 133 | if(!MG::isAdmin()) 134 | return false; 135 | return MG::DB()->exec("delete from user_group_bind where users_id=? and user_group_id=?",$userId,$groupId) === 1; 136 | } 137 | public static function JS_getUserGroups($userId){ 138 | if(!MG::isAdmin()) 139 | return false; 140 | return Self::getGroups($userId); 141 | } 142 | } -------------------------------------------------------------------------------- /PHP/include/Database.php: -------------------------------------------------------------------------------- 1 | mDB = new PDO("$driver:dbname=$dbname", $user, $pass); 9 | else 10 | $this->mDB = new PDO("$driver:host=$server;dbname=$dbname", $user, $pass); 11 | if(!$this->mDB) 12 | return false; 13 | $this->mDB->setAttribute(PDO::ERRMODE_WARNING, PDO::ERRMODE_EXCEPTION); 14 | $this->mDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 15 | return true; 16 | }catch(Exception $e){ 17 | return false; 18 | } 19 | } 20 | public function _connect2($str){ 21 | try{ 22 | $this->mDB = new PDO($str); 23 | if(!$this->mDB) 24 | return false; 25 | $this->mDB->setAttribute(PDO::ERRMODE_WARNING, PDO::ERRMODE_EXCEPTION); 26 | $this->mDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 27 | return true; 28 | }catch(Exception $e){ 29 | return false; 30 | } 31 | } 32 | public function isConnect(){ 33 | return $this->mDB !== null; 34 | } 35 | public function setOnError($proc){ 36 | $this->mErrorProc = $proc; 37 | } 38 | public function getHandle(){ 39 | return $this->mDB; 40 | } 41 | public function close(){ 42 | $mDB = null; 43 | } 44 | public function createUpdateParam($array,$keys){ 45 | $param = ""; 46 | foreach($array as $key => $value){ 47 | //プライマリキーを除外 48 | if(isset($keys[$key])) 49 | continue; 50 | if(strlen($param)>0) 51 | $param .=","; 52 | $param .= sprintf("%s=%s",$key,$value!=null?$this->quote($value):'null'); 53 | } 54 | return $param; 55 | } 56 | public function createNameParam($array){ 57 | $param = ""; 58 | foreach($array as $key => $value){ 59 | if(strlen($param)>0) 60 | $param .=","; 61 | $param .= $key; 62 | } 63 | return $param; 64 | } 65 | public function createValueParam($array){ 66 | $param = ""; 67 | foreach($array as $key => $value){ 68 | if(strlen($param)>0) 69 | $param .=","; 70 | $param .= $value!=null?$this->quote($value):'null'; 71 | } 72 | return $param; 73 | } 74 | public function createKeyParam($values,$keys){ 75 | $param = ""; 76 | foreach($keys as $key){ 77 | if(strlen($param)>0) 78 | $param .=" and "; 79 | $param .= sprintf("%s=%s",$key,$values[$key]!=null?$this->quote($values[$key]):'null'); 80 | } 81 | return $param; 82 | } 83 | public function quote($value){ 84 | return $this->mDB->quote($value); 85 | } 86 | public function gets($sql,...$params){ 87 | $stmt = $this->query($sql,...$params); 88 | if($stmt && $row=$stmt->fetch(PDO::FETCH_ASSOC)) 89 | return $row; 90 | return null; 91 | } 92 | public function gets2($sql,...$params){ 93 | $stmt = $this->query($sql,...$params); 94 | if($row=$stmt->fetch(PDO::FETCH_NUM)) 95 | return $row; 96 | return null; 97 | } 98 | public function get($sql,...$params){ 99 | $stmt = $this->query($sql,...$params); 100 | if($stmt !== null &&$row=$stmt->fetch(PDO::FETCH_NUM)) 101 | return $row[0]; 102 | return null; 103 | } 104 | public function query($sql,...$params){ 105 | try{ 106 | if($this->mDB === null) 107 | return false; 108 | $stmt = $this->mDB->prepare($sql); 109 | if($params !== null){ 110 | foreach($params as $index => $param){ 111 | $type = gettype($param) ; 112 | if($type == "resource") 113 | $stmt->bindValue($index+1,$param,PDO::PARAM_LOB); 114 | else if($type == "date") 115 | $stmt->bindValue($index+1,$param,PDO::PARAM_STR); 116 | else 117 | $stmt->bindValue($index+1,$param); 118 | } 119 | } 120 | $stmt->execute(); 121 | if($this->mDB->errorInfo()[0] != 0){ 122 | if($mErrorProc !== null) 123 | call_user_func($mErrorProc, $this->mDB->errorInfo()[0],$sql); 124 | } 125 | return $stmt; 126 | }catch(PDOException $exception){ 127 | //if($this->mErrorProc !== null) 128 | //call_user_func($this->mErrorProc, $exception->getMessage(),$sql); 129 | } 130 | return null; 131 | } 132 | public function execute($sql){ 133 | try{ 134 | $stmt = $this->mDB->exec($sql); 135 | if($params !== null){ 136 | foreach($params as $index => $param){ 137 | if(gettype($param) == "resource") 138 | $stmt->bindValue($index+1,$param,PDO::PARAM_LOB); 139 | else 140 | $stmt->bindValue($index+1,$param); 141 | } 142 | } 143 | $stmt->execute(); 144 | return $stmt->rowCount(); 145 | }catch(PDOException $exception){ 146 | if($this->mErrorProc !== null) 147 | call_user_func($this->mErrorProc, $exception->getMessage(),$sql); 148 | } 149 | return null; 150 | } 151 | public function exec($sql,...$params){ 152 | try{ 153 | if($this->mDB === null) 154 | return false; 155 | if($params !== null && count($params)){ 156 | $stmt = $this->mDB->prepare($sql); 157 | foreach($params as $index => $param){ 158 | if(gettype($param) == "resource") 159 | $stmt->bindValue($index+1,$param,PDO::PARAM_LOB); 160 | else 161 | $stmt->bindValue($index+1,$param); 162 | } 163 | $stmt->execute(); 164 | return $stmt->rowCount(); 165 | }else 166 | return $this->mDB->exec($sql); 167 | 168 | }catch(PDOException $exception){ 169 | if($this->mErrorProc !== null){ 170 | //call_user_func($this->mErrorProc, $exception->getMessage(),$sql); 171 | } 172 | } 173 | return null; 174 | } 175 | public function replace($table,$keys,$values){ 176 | $strKey = $this->createKeyParam($values,$keys); 177 | $names = $this->createNameParam($values); 178 | $updates = $this->createUpdateParam($values,$keys); 179 | $values = $this->createValueParam($values); 180 | 181 | $sql = sprintf("update %s set %s where %s;",$table,$updates,$strKey); 182 | $count = $this->exec($sql); 183 | if($count > 0) 184 | return $count; 185 | $sql = sprintf("insert into %s(%s) select %s where not exists (select 1 from %s where %s);", 186 | $table,$names,$values,$table,$strKey); 187 | return $this->exec($sql); 188 | } 189 | 190 | 191 | public function isSequence($name){ 192 | $sql = sprintf("SELECT c.relname FROM pg_class c LEFT join pg_user u ON c.relowner = u.usesysid WHERE c.relkind = 'S' and c.relname=%s", 193 | $this->mDB->quote($name)); 194 | $stmt = $this->query($sql); 195 | return $stmt->fetch(PDO::FETCH_NUM)!=null; 196 | } 197 | public function queryFormatData(){ 198 | $args = func_get_args(); 199 | $vargs = array_slice($args,1); 200 | $sql = vsprintf($args[0],$vargs); 201 | return $this->queryData($sql); 202 | } 203 | public function queryData($sql,...$params){ 204 | $stmt = $this->query($sql,...$params); 205 | if($stmt == null) 206 | return null; 207 | return $stmt->fetchAll(PDO::FETCH_ASSOC); 208 | } 209 | public function queryData2($sql,...$params){ 210 | $stmt = $this->query($sql,...$params); 211 | if($stmt == null) 212 | return null; 213 | //データの取得 214 | $datas = Array(); 215 | while($row=$stmt->fetch(PDO::FETCH_NUM)) 216 | { 217 | $datas[] = $row; 218 | } 219 | return $datas; 220 | } 221 | } -------------------------------------------------------------------------------- /PHP/include/PostgreSQL.php: -------------------------------------------------------------------------------- 1 | quote($name)); 10 | $stmt = $this->query($sql); 11 | return $stmt->fetch(PDO::FETCH_NUM)!=null; 12 | } 13 | } 14 | 15 | 16 | ?> 17 | -------------------------------------------------------------------------------- /PHP/include/SQLite.php: -------------------------------------------------------------------------------- 1 | quote($name)); 10 | $stmt = $this->query($sql); 11 | return $stmt->fetch(PDO::FETCH_NUM)!=null; 12 | } 13 | } 14 | 15 | ?> -------------------------------------------------------------------------------- /css/Gui.css: -------------------------------------------------------------------------------- 1 | .GUIArea{ 2 | box-sizing: border-box; 3 | position: fixed; 4 | left: 0px; 5 | top: 0px; 6 | } 7 | .GUIArea .GUIWindow{ 8 | box-sizing: border-box; 9 | position: absolute; 10 | } 11 | 12 | .GUIArea .GUIWindow#frame{ 13 | animation: fadeIn 0.5s ease 0s 1 normal; 14 | box-shadow: 10px 10px 10px rgba(0,0,0,0.4); 15 | border-radius: 10px 10px 0px 0px; 16 | border: 1px solid rgba(0,0,0,0.8); 17 | } 18 | 19 | @keyframes fadeIn { 20 | 0% {opacity: 0;transform: scale(0.0);} 21 | 100% {opacity: 1;transform: scale(1.0);} 22 | } 23 | 24 | .GUIArea .GUIWindow .GUIFrame{ 25 | display: none; 26 | } 27 | .GUIArea .GUIWindow#frame > .GUIFrame{ 28 | display: block; 29 | } 30 | 31 | .GUIArea .GUIWindow .GUIBorderLeft{ 32 | position: absolute; 33 | left: -10px; 34 | width: 10px; 35 | height: 100%; 36 | cursor: w-resize; 37 | } 38 | .GUIArea .GUIWindow .GUIBorderRight{ 39 | position: absolute; 40 | left: 100%; 41 | width: 10px; 42 | height: 100%; 43 | cursor: e-resize; 44 | } 45 | .GUIArea .GUIWindow .GUIBorderTop{ 46 | position: absolute; 47 | top: -10px; 48 | width: 100%; 49 | height: 10px; 50 | cursor: n-resize; 51 | } 52 | .GUIArea .GUIWindow .GUIBorderBottom{ 53 | position: absolute; 54 | top: 100%; 55 | width: 100%; 56 | height: 10px; 57 | cursor: s-resize; 58 | } 59 | .GUIArea .GUIWindow .GUIBorderTopLeft{ 60 | position: absolute; 61 | top: -10px; 62 | left: -10px; 63 | width: 10px; 64 | height: 10px; 65 | cursor: nw-resize; 66 | } 67 | .GUIArea .GUIWindow .GUIBorderTopRight{ 68 | position: absolute; 69 | top: -10px; 70 | left: 100%; 71 | width: 10px; 72 | height: 10px; 73 | cursor: ne-resize; 74 | } 75 | .GUIArea .GUIWindow .GUIBorderBottomLeft{ 76 | position: absolute; 77 | top: 100%; 78 | left: -10px; 79 | width: 10px; 80 | height: 10px; 81 | cursor: sw-resize; 82 | } 83 | .GUIArea .GUIWindow .GUIBorderBottomRight{ 84 | position: absolute; 85 | top: 100%; 86 | left: 100%; 87 | width: 10px; 88 | height: 10px; 89 | cursor: se-resize; 90 | } 91 | .GUIArea .GUIWindow .GUITitle{ 92 | position: relative; 93 | height: 30px; 94 | border-radius: 10px 10px 0px 0px; 95 | background-color: #7567eb; 96 | cursor: move; 97 | overflow: hidden; 98 | white-space: nowrap; 99 | } 100 | .GUIArea .GUIWindow .GUITitle .GUITitleIcons{ 101 | position: absolute; 102 | top: 0px; 103 | right: 10px; 104 | height: 30px; 105 | white-space: nowrap; 106 | } 107 | .GUIArea .GUIWindow .GUITitle .GUITitleText{ 108 | position: absolute; 109 | vertical-align: middle; 110 | margin-left: 10px; 111 | line-height: 30px; 112 | color: white; 113 | } 114 | 115 | .GUIArea .GUIWindow .GUITitle .GUITitleIcons div{ 116 | display: inline-block; 117 | height: 30px; 118 | width: 30px; 119 | cursor: default; 120 | background-size: 100% 100%; 121 | } 122 | .GUIArea .GUIWindow .GUITitle .GUITitleIcons div:hover{ 123 | background-color: rgba(0,0,0,0.2) 124 | } 125 | 126 | .GUIArea .GUIWindow .GUITitle .GUITitleMin{ 127 | background-image: url("images/min.svg"); 128 | 129 | } 130 | .GUIArea .GUIWindow .GUITitle .GUITitleClose{ 131 | background-image: url("images/close.svg"); 132 | } 133 | .GUIArea .GUIWindow .GUITitle .GUITitleMax{ 134 | background-image: url("images/max.svg"); 135 | } 136 | .GUIArea .GUIWindow .GUITitle .GUITitleNormal{ 137 | background-image: url("images/normal.svg"); 138 | } 139 | .GUIArea .GUIButton{ 140 | box-sizing: border-box; 141 | background-color: darkgray; 142 | border-width: 1px; 143 | border-style: solid; 144 | border-color: whitesmoke dimgrey dimgrey whitesmoke; 145 | padding: 2px; 146 | } 147 | .GUIArea .GUIPanel{ 148 | display: flex; 149 | white-space: nowrap; 150 | box-sizing: border-box; 151 | background-color: darkgray; 152 | border-width: 1px; 153 | border-style: solid; 154 | border-color: whitesmoke dimgrey dimgrey whitesmoke; 155 | padding: 2px; 156 | } 157 | @keyframes minimize { 158 | 100% {height: 0px;} 159 | } 160 | @keyframes restore { 161 | 0% {height: 0px;} 162 | } 163 | @keyframes maximize { 164 | 0% {transform: scale(0)} 165 | 100% {transform: scale(1)} 166 | } 167 | @keyframes maxrestore { 168 | 0% {transform: scale(2)} 169 | 100% {transform: scale(1)} 170 | } 171 | @keyframes close { 172 | 100% {opacity: 0;transform: scale(0.0);} 173 | } 174 | 175 | .GUIArea .GUIWindow .GUIClient{ 176 | position: relative; 177 | height: 200px; 178 | background-color: #ffffff; 179 | overflow: hidden; 180 | } 181 | 182 | 183 | .GUIArea .GUIWindow#root >.GUIClient{ 184 | margin: 0px; 185 | height: 0px; 186 | width: 0px; 187 | background-color: transparent; 188 | overflow: visible; 189 | } 190 | 191 | 192 | .GUIArea .GUIWindow #GUISeparate > .GUIClient{ 193 | user-select: none; 194 | box-sizing: border-box; 195 | background-color: #aaaaaa; 196 | border: outset 2px #b8b7b7; 197 | } 198 | .GUIArea .GUIWindow #GUISeparate > .GUIClient#ns,#sn{ 199 | cursor: ns-resize; 200 | } 201 | .GUIArea .GUIWindow #GUISeparate > .GUIClient#we,#ew{ 202 | cursor: ew-resize; 203 | } 204 | .GUIArea .GUIWindow .GUIClient .GUITreeView{ 205 | overflow: auto; 206 | user-select: none; 207 | } 208 | .GUIArea .GUIWindow .GUIClient .GUITreeItem{ 209 | display: flex; 210 | flex-direction : column; 211 | } 212 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow{ 213 | display: flex; 214 | } 215 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow > .GUITreeChild{ 216 | flex: 1; 217 | } 218 | 219 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow > .GUITreeBody{ 220 | flex: 1; 221 | } 222 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow:first-child:hover{ 223 | border-bottom: black 1px solid; 224 | } 225 | @keyframes treeOpen { 226 | 0% {margin-top:-1.5em;opacity: 0.2;} 227 | 100% {margin-top:0%;} 228 | } 229 | @keyframes treeClose { 230 | 0% {margin-top:0;opacity: 0.6;} 231 | 90% {margin-top:-2em;opacity: 0.6;} 232 | 100%{margin-top:-100%;transform:scaleY(0);opacity: 0;visibility:hidden;} 233 | } 234 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow:nth-child(2) > .GUITreeChild { 235 | overflow: hidden; 236 | } 237 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow:nth-child(2) > .GUITreeChild .GUITreeItem{ 238 | padding-left: 1em; 239 | flex: 1; 240 | } 241 | /* 242 | .GUIArea .GUIWindow .GUIClient .GUITreeItem#open > .GUITreeRow:nth-child(2) > .GUITreeChild > .GUITreeItem{ 243 | animation: treeOpen 0.3s ease 0s 1 normal; 244 | } 245 | 246 | .GUIArea .GUIWindow .GUIClient .GUITreeItem#close > .GUITreeRow:nth-child(2) > .GUITreeChild { 247 | animation: treeClose 0.8s linear 0s 1 forwards; 248 | } 249 | */ 250 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow > .GUITreeIcon{ 251 | background-repeat: no-repeat; 252 | width: 16px; 253 | height: 16px; 254 | margin: 2px; 255 | vertical-align: middle; 256 | } 257 | 258 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow > .GUITreeIcon{ 259 | cursor: default; 260 | } 261 | .GUIArea .GUIWindow .GUIClient .GUITreeItem#close > .GUITreeRow > .GUITreeIcon{ 262 | background-image: url("images/tclose.svg"); 263 | } 264 | .GUIArea .GUIWindow .GUIClient .GUITreeItem#open > .GUITreeRow > .GUITreeIcon{ 265 | background-image: url("images/topen.svg"); 266 | } 267 | .GUIArea .GUIWindow .GUIClient .GUITreeItem#alone > .GUITreeRow > .GUITreeIcon{ 268 | background-image: url("images/talone.svg"); 269 | } 270 | 271 | .GUIArea .GUIWindow .GUIClient .GUITreeItem > .GUITreeRow:first-child { 272 | cursor: pointer; 273 | } 274 | .GUIArea .GUIWindow .GUIClient .GUITreeItem[data-select="true"] > .GUITreeRow:first-child { 275 | background-color: rgba(80, 80, 233, 0.2); 276 | } 277 | 278 | .GUIListView{ 279 | user-select: none; 280 | background-color: aqua; 281 | } 282 | .ListWork{ 283 | visibility: hidden; 284 | position: fixed; 285 | } 286 | .GUIListView .Item{ 287 | box-sizing: border-box; 288 | position: absolute; 289 | overflow: hidden; 290 | white-space: nowrap; 291 | } 292 | .GUIListView .Header{ 293 | z-index: 1; 294 | text-align: center; 295 | cursor: pointer; 296 | white-space: pre; 297 | background-color: rgba(200,200,200,0.8); 298 | border: solid 1px; 299 | border-color: #AAAAAA black black #AAAAAA; 300 | } 301 | .GUIListView .Header.Select{ 302 | background-color: rgba(151, 151, 151, 0.9); 303 | } 304 | .GUIListView .Item.Item0{ 305 | background-color: rgba(252, 250, 136, 0.8); 306 | } 307 | .GUIListView .Item.Item1{ 308 | background-color: rgba(223, 252, 228, 0.8); 309 | } 310 | .GUIListView .Item.Left{ 311 | text-align: left; 312 | } 313 | .GUIListView .Item.Right{ 314 | text-align: right; 315 | } 316 | .GUIListView .Item.ItemOver{ 317 | border-top: 2px solid rgba(0,0,0,0.1); 318 | border-bottom: 2px solid rgba(0,0,0,0.1); 319 | transform: scale(1.2); 320 | transform-origin: 10%; 321 | 322 | } 323 | .GUIListView .Item.ItemSelect{ 324 | background-color: rgba(255,230,230,1.0); 325 | } 326 | .GUIListView .Item .Folder{ 327 | background-image: url("images/folder.svg"); 328 | background-size: contain; 329 | background-repeat: no-repeat; 330 | background-position: center; 331 | } 332 | .GUIListView .Item .File{ 333 | background-image: url("images/file.svg"); 334 | background-size: contain; 335 | background-repeat: no-repeat; 336 | background-position: center; 337 | } 338 | .GUIMoveNode{ 339 | position: fixed; 340 | z-index: 200; 341 | background-color: rgba(164, 173, 214, 0.589); 342 | background-image: url("images/file.svg"); 343 | pointer-events: none; 344 | } 345 | .GUISelect{ 346 | box-sizing: border-box; 347 | user-select: none; 348 | vertical-align: middle; 349 | overflow-wrap: break-word; 350 | overflow: auto; 351 | padding: 2px; 352 | } 353 | .GUISelect div{ 354 | margin: 1px; 355 | padding: 1px; 356 | cursor: pointer; 357 | background-color: rgba(200,200,200,0.9); 358 | } 359 | .GUISelect div:hover{ 360 | background-color: rgba(230,230,230,0.9); 361 | } 362 | 363 | .GUIEditText{ 364 | box-sizing: border-box; 365 | user-select: text; 366 | background-color: rgba(200,200,200,0.9); 367 | overflow-wrap: break-word; 368 | overflow: auto; 369 | vertical-align: middle; 370 | padding: 2px; 371 | white-space: pre; 372 | 373 | } 374 | .GUICalendar table{ 375 | user-select: none; 376 | table-layout: fixed; 377 | border-collapse: collapse; 378 | width: 100%; 379 | height: 100%; 380 | } 381 | .GUICalendar .TitleLine{ 382 | background-color: rgb(255, 224, 216); 383 | 384 | } 385 | .GUICalendar .TitleLine .TitleText{ 386 | text-align: center; 387 | } 388 | .GUICalendar .TitleLine .Button{ 389 | text-align: center; 390 | cursor: pointer; 391 | background-color: rgb(195, 215, 216); 392 | } 393 | 394 | .GUICalendar .Cell{ 395 | border: 2px solid #aaaaaa; 396 | background-color: antiquewhite; 397 | } 398 | .GUICalendar .Line:first-child .Cell{ 399 | vertical-align: middle; 400 | text-align: center; 401 | font-size: 200%; 402 | 403 | } 404 | .GUICalendar Table .Line:nth-of-type(2){ 405 | text-align: center; 406 | } 407 | .GUICalendar Table .Line:nth-of-type(2) .Cell:first-child{ 408 | color: red; 409 | } 410 | .GUICalendar Table .Line:nth-of-type(2) .Cell:last-child{ 411 | color: blue; 412 | } 413 | .CellBody { 414 | box-sizing: border-box; 415 | position: relative; 416 | width: 100%; 417 | height: 100%; 418 | } 419 | .CellBody#now{ 420 | border: #7567eb solid; 421 | } 422 | .CellBody:hover{ 423 | display: block; 424 | background-color: rgba(200,200,200,0.3); 425 | } 426 | .GUICalendar .Cell{ 427 | display: table-cell; 428 | } 429 | .GUICalendar .Cell .Day{ 430 | font-size: 110%; 431 | text-align: right; 432 | padding: 1px; 433 | } 434 | .GUICalendar .Cell .DayText{ 435 | font-weight: bold; 436 | color: red; 437 | text-align: center; 438 | padding: 2px; 439 | overflow: hidden; 440 | white-space: nowrap; 441 | font-size: 80%; 442 | height: 1.2em; 443 | 444 | 445 | } 446 | .GUICalendar .Cell#Holiday .DayText{ 447 | background-color: rgb(253, 167, 135); 448 | } 449 | .GUICalendar .Cell:first-child .Day{ 450 | color: red; 451 | } 452 | .GUICalendar .Cell:last-child .Day{ 453 | color: red; 454 | } 455 | .GUICalendar .Cell#Holiday .Day{ 456 | color: red; 457 | } 458 | 459 | 460 | 461 | .GUIMessageBox .MSG{ 462 | display: flex; 463 | justify-content: center; 464 | align-items: center; 465 | } 466 | .GUIMessageBox .PANEL{ 467 | display: flex; 468 | justify-content: center; 469 | align-items: center; 470 | } 471 | 472 | .GUITextInput input,.GUITextInput button{ 473 | width: 100%; 474 | height: 100%; 475 | } 476 | -------------------------------------------------------------------------------- /css/Main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-family: Arial, Helvetica, sans-serif; 3 | } 4 | .LayoutTop{ 5 | display: flex; 6 | align-items: center; 7 | background-color: darkgrey; 8 | align-items: center; 9 | } 10 | .LayoutTop > div.topTitle{ 11 | font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; 12 | font-size: 250%; 13 | color: white; 14 | margin-left: 1em; 15 | white-space: nowrap; 16 | } 17 | .LayoutTop > div.menuItems{ 18 | overflow: auto; 19 | white-space: nowrap; 20 | display: flex; 21 | flex: 1; 22 | flex-direction: row-reverse; 23 | } 24 | 25 | div.menuItem{ 26 | background-color: rgba(255,255,255,0.5); 27 | text-shadow: 1px 1px 0 rgba(255, 254, 254, 0.842); 28 | padding: 8px; 29 | border-radius: 20%; 30 | margin: 4px; 31 | cursor: pointer; 32 | user-select: none; 33 | } 34 | 35 | div.ParamsEditView{ 36 | display: flex; 37 | } 38 | div.ParamsEditView > div{ 39 | margin: 1em; 40 | display: inline-flex; 41 | justify-content: center; 42 | align-items: center; 43 | flex-direction : column; 44 | padding: 1em; 45 | background-color: rgba(33, 111, 163, 0.7) !important; 46 | color: white; 47 | border-radius: 10px; 48 | 49 | } 50 | .ParamsEditView input{ 51 | position: relative; 52 | margin: 10px; 53 | background-color: rgba(240, 255, 255, 0.7) !important; 54 | padding: 8px; 55 | border: 2px solid aquamarine; 56 | border-radius: 10px; 57 | color: black; 58 | width: 200px; 59 | font-family: Consolas, 'Courier New', Courier, Monaco, monospace; 60 | font-size: 16px; 61 | font-weight: bold; 62 | 63 | } 64 | 65 | .ParamsEditView > DIV>DIV>DIV>DIV{ 66 | position: absolute; 67 | margin: 10px; 68 | padding: 8px; 69 | white-space: nowrap; 70 | } 71 | 72 | button.blueButton{ 73 | margin: 0.5em; 74 | padding: 7px 20px; 75 | border-radius: 25px; 76 | text-decoration: none; 77 | color: #FFF; 78 | background-image: linear-gradient(45deg, rgb(7, 143, 255) 0%, #491bdf 100%); 79 | transition: .4s; 80 | border: none; 81 | border-bottom: solid 3px #3201d6; 82 | } 83 | 84 | button.blueButton:hover { 85 | background-image: linear-gradient(45deg, rgba(7, 143, 255, 0.842) 0%, #491bdfc5 100%); 86 | border-bottom: none; 87 | } 88 | 89 | div.InputArea{ 90 | display: inline-flex; 91 | margin: 2em; 92 | padding:0.2em; 93 | border-radius: 10px; 94 | background-color: rgba(53, 121, 167, 0.7); 95 | min-width: 300px; 96 | } 97 | 98 | div.BoxView{ 99 | overflow: auto !important; 100 | } 101 | div.BoxView > div{ 102 | display: inline-flex; 103 | flex-direction : row; 104 | margin: 1em; 105 | border-radius: 10px; 106 | background-color: rgba(33, 111, 163, 0.7); 107 | padding:0.2em; 108 | min-width: 300px; 109 | } 110 | 111 | div.BoxView > div > div:first-child > div{ 112 | background-color: rgba(17, 87, 134, 0.7); 113 | } 114 | div.BoxView > div > div:nth-child(2){ 115 | flex: 1; 116 | } 117 | div.BoxView > div > div:nth-child(2) > div{ 118 | background-color: rgba(17, 87, 134, 0.4); 119 | } 120 | div.BoxView > div > div > div{ 121 | color: white; 122 | padding: 0.3em; 123 | margin: 0.2em; 124 | } 125 | 126 | div.GroupView{ 127 | display: inline-flex; 128 | align-items: center; 129 | flex-direction : column; 130 | margin: 1em; 131 | } 132 | 133 | div.QiitaInfoView{ 134 | display: inline-flex; 135 | justify-content: center; 136 | align-items: center; 137 | flex-direction : column; 138 | } 139 | 140 | input.title{ 141 | flex: 1; 142 | } 143 | 144 | div.TreeOption{ 145 | position: absolute; 146 | right:0; 147 | } 148 | div.TreeOption span{ 149 | width: 1.2em; 150 | display: inline-block; 151 | margin: 1px; 152 | padding: 0 2px; 153 | background-color: rgba(100,200,100,0.95); 154 | text-align: center; 155 | } 156 | div.TreeOption span:hover{ 157 | background-color: rgba(100,200,200,0.95); 158 | } 159 | @keyframes PageShow { 160 | 0% {opacity: 0.1;} 161 | 100% {opacity: 1;} 162 | } 163 | .ContentsPage{ 164 | position: relative; 165 | margin: 1em; 166 | background-color: #f5f5f5; 167 | padding:0.5em; 168 | border-radius: 9px; 169 | 170 | } 171 | 172 | .ContentsArea{ 173 | position: relative; 174 | display: flex; 175 | flex-direction: column; 176 | padding-left: 1em; 177 | animation: PageShow 0.5s ease 0s 1 normal; 178 | } 179 | 180 | [data-visible="false"] .ContentsArea:not([data-stat="1"]){ 181 | display: none; 182 | } 183 | .ContentsArea[data-stat="0"]{ 184 | border: blue solid; 185 | } 186 | .ContentsArea[data-stat="-1"]{ 187 | border: red solid; 188 | } 189 | .Contents .Title0{ 190 | display: none; 191 | } 192 | .Contents .Title1{ 193 | font-size: 250%; 194 | border-bottom: solid 2px orange; 195 | padding: 0.0em; 196 | } 197 | .Contents .Title2{ 198 | font-size: 180%; 199 | border-bottom: solid 1px orange; 200 | padding: 0.0em; 201 | margin-top: 1em; 202 | } 203 | .Contents .Title3{ 204 | font-size: 130%; 205 | padding: 0.0em; 206 | } 207 | .Contents .Date{ 208 | text-align: right; 209 | padding: 0.1em; 210 | } 211 | .Contents .Body{ 212 | padding-left: 1.2em; 213 | border-left: dashed #ffffff; 214 | } 215 | .Contents{ 216 | margin-bottom: 2em; 217 | } 218 | .Contents .Panel{ 219 | margin: 0.1em; 220 | display: none; 221 | position: absolute; 222 | right: 0.1em; 223 | top: 0.1em; 224 | } 225 | .Contents:hover .Panel{ 226 | display: flex; 227 | } 228 | .Contents .Panel div{ 229 | border: solid rgb(141, 162, 184); 230 | background: rgb(161, 161, 250); 231 | color: white; 232 | padding: 0.1em; 233 | margin: 0.1em; 234 | cursor: pointer; 235 | } 236 | .GUITreeItem { 237 | padding-left: 0; 238 | color: black; 239 | } 240 | .GUITreeItem[data-type='TEXT'] { 241 | padding-left: 0.8em; 242 | color: #008127; 243 | } 244 | 245 | .GUITreeItem[data-stat='0'] >div> .GUITreeBody{ 246 | text-decoration: line-through blue; 247 | } 248 | .GUITreeItem[data-stat='-1'] >div>.GUITreeBody{ 249 | text-decoration: line-through red ; 250 | } 251 | [data-visible="false"] .GUITreeItem:matches([data-stat="-1"] [data-stat="0"]) { 252 | display: none !important; 253 | } 254 | 255 | .GUIMenu{ 256 | user-select: none; 257 | animation: fadeIn 0.2s ease 0s 1 normal; 258 | padding: 1px; 259 | position: absolute; 260 | z-index: 10; 261 | background-color: #ddddd6; 262 | } 263 | .GUIMenu > div{ 264 | background: rgba(200,200,250,0.85); 265 | cursor: pointer; 266 | margin: 1px; 267 | padding: 2px; 268 | } 269 | .GUIMenu > div:hover{ 270 | background: #8888ff; 271 | } 272 | 273 | div.Import{ 274 | height: 100%; 275 | display: flex; 276 | flex-direction: column; 277 | justify-content: center; 278 | align-items: center; 279 | 280 | } 281 | 282 | .code,.code2{ 283 | overflow: auto; 284 | display: inline-block; 285 | border: dashed rgba(0,0,0,0.05); 286 | font-size: 110%; 287 | font-weight: bold; 288 | padding: 0.5em !important; 289 | white-space: nowrap; 290 | font-family: MeiryoKe_Gothic, "Ricty Diminished", "Osaka-等幅", "Osaka-等幅", Osaka-mono, "MS ゴシック", "MS Gothic", "Courier New", Courier, Monaco, Menlo, Consolas, "Lucida Console", monospace; 291 | } 292 | 293 | .update{ 294 | display: inline-block; 295 | padding: 0.5em !important; 296 | } 297 | .update div{ 298 | cursor: pointer; 299 | margin: 0.4em; 300 | } 301 | .update div:hover{ 302 | cursor: pointer; 303 | background-color: aliceblue; 304 | } 305 | .update span{ 306 | margin: 0.2em; 307 | padding: 0.2em; 308 | border-bottom: dashed rgba(0,0,0,0.05); 309 | } 310 | .video-container { 311 | position: relative;padding-bottom: 56.25%;padding-top: 30px;height: 0;overflow: hidden;} 312 | .video-container iframe,.video-container object,.video-container embed { 313 | position: absolute;top: 0;left: 0;width: 90%;height: 100%;} 314 | -------------------------------------------------------------------------------- /css/TextEditor.css: -------------------------------------------------------------------------------- 1 | .TextEdit{ 2 | opacity: 0.9; 3 | } 4 | .TextEditArea textarea,.HtmlEditArea iframe{ 5 | width: 100%; 6 | height: 100%; 7 | } 8 | .TextEditArea textarea{ 9 | word-break: break-all; 10 | overflow: auto; 11 | line-height: 150%; 12 | 13 | } 14 | .PanelArea{ 15 | padding: 1px; 16 | } 17 | 18 | .PanelArea span{ 19 | box-sizing:border-box; 20 | margin-left: 4px; 21 | padding: 2px; 22 | background-color: rgba(255,255,255,0.5); 23 | 24 | } 25 | .PanelArea button{ 26 | height: 100%; 27 | } 28 | .PanelArea .textsize{ 29 | background-color: aliceblue; 30 | padding: 0px; 31 | display: inline-block; 32 | text-align: center; 33 | width: 2em; 34 | } -------------------------------------------------------------------------------- /css/images/close.svg: -------------------------------------------------------------------------------- 1 | close -------------------------------------------------------------------------------- /css/images/file.svg: -------------------------------------------------------------------------------- 1 | file -------------------------------------------------------------------------------- /css/images/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 158 | 159 | -------------------------------------------------------------------------------- /css/images/max.svg: -------------------------------------------------------------------------------- 1 | max -------------------------------------------------------------------------------- /css/images/min.svg: -------------------------------------------------------------------------------- 1 | min -------------------------------------------------------------------------------- /css/images/normal.svg: -------------------------------------------------------------------------------- 1 | 2 | normal 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /css/images/talone.svg: -------------------------------------------------------------------------------- 1 | talone -------------------------------------------------------------------------------- /css/images/tclose.svg: -------------------------------------------------------------------------------- 1 | tclose -------------------------------------------------------------------------------- /css/images/topen.svg: -------------------------------------------------------------------------------- 1 | topen -------------------------------------------------------------------------------- /css/routeros.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | highlight.js style for Microtik RouterOS script 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #F0F0F0; 12 | } 13 | 14 | /* Base color: saturation 0; */ 15 | 16 | .hljs, 17 | .hljs-subst { 18 | color: #444; 19 | } 20 | 21 | .hljs-comment { 22 | color: #888888; 23 | } 24 | 25 | .hljs-keyword, 26 | .hljs-selector-tag, 27 | .hljs-meta-keyword, 28 | .hljs-doctag, 29 | .hljs-name { 30 | font-weight: bold; 31 | } 32 | 33 | .hljs-attribute { 34 | color: #0E9A00; 35 | } 36 | 37 | .hljs-function { 38 | color: #99069A; 39 | } 40 | 41 | .hljs-builtin-name { 42 | color: #99069A; 43 | } 44 | 45 | /* User color: hue: 0 */ 46 | 47 | .hljs-type, 48 | .hljs-string, 49 | .hljs-number, 50 | .hljs-selector-id, 51 | .hljs-selector-class, 52 | .hljs-quote, 53 | .hljs-template-tag, 54 | .hljs-deletion { 55 | color: #880000; 56 | } 57 | 58 | .hljs-title, 59 | .hljs-section { 60 | color: #880000; 61 | font-weight: bold; 62 | } 63 | 64 | .hljs-regexp, 65 | .hljs-symbol, 66 | .hljs-variable, 67 | .hljs-template-variable, 68 | .hljs-link, 69 | .hljs-selector-attr, 70 | .hljs-selector-pseudo { 71 | color: #BC6060; 72 | } 73 | 74 | 75 | /* Language color: hue: 90; */ 76 | 77 | .hljs-literal { 78 | color: #78A960; 79 | } 80 | 81 | .hljs-built_in, 82 | .hljs-bullet, 83 | .hljs-code, 84 | .hljs-addition { 85 | color: #0C9A9A; 86 | } 87 | 88 | 89 | /* Meta color: hue: 200 */ 90 | 91 | .hljs-meta { 92 | color: #1f7199; 93 | } 94 | 95 | .hljs-meta-string { 96 | color: #4d99bf; 97 | } 98 | 99 | 100 | /* Misc effects */ 101 | 102 | .hljs-emphasis { 103 | font-style: italic; 104 | } 105 | 106 | .hljs-strong { 107 | font-weight: bold; 108 | } 109 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | \n"; 28 | }else{ 29 | $scripts .= "\t\n"; 30 | } 31 | $links[] = "$path/$file?ver=$date"; 32 | } 33 | } 34 | return $scripts; 35 | } 36 | 37 | 38 | function outputFile($fileName){ 39 | $links = []; 40 | $scripts = outputScript("css", $links, "css"); 41 | $scripts .= outputScript("JavaScript/include", $links,'js'); 42 | $scripts .= outputScript("JavaScript", $links,'js'); 43 | 44 | foreach ($links as $link) { 45 | header("link: <$link>;rel=preload;as=script;", false); 46 | } 47 | 48 | 49 | $analytics = Params::getParam("Global_base_analytics", ""); 50 | if($analytics!=""){ 51 | $scripts .= sprintf( 52 | "\t\n". 53 | "\t\n", 60 | $analytics, $analytics); 61 | } 62 | $adsense = Params::getParam("Global_base_adsense", ""); 63 | if($adsense!=""){ 64 | $scripts .= sprintf( 65 | "\t\n". 66 | "\t\n", 72 | $adsense); 73 | } 74 | //パンくずリスト 75 | $scripts .= "\t".Contents::getBreadcrumb()."\n"; 76 | //正規URL 77 | $scripts .= "\t" . Contents::getCanonical()."\n"; 78 | $title = Contents::getTitle(); 79 | //圧縮 80 | //ob_start("ob_gzhandler"); 81 | // Last-modified と ETag 生成 82 | $last_modified = gmdate( "D, d M Y H:i:s T", filemtime($fileName) ); 83 | $etag = md5( $last_modified.$fileName); 84 | // ヘッダ送信 85 | header( "Last-Modified: {$last_modified}" ); 86 | header( "Etag: {$etag}" ); 87 | $contents = file_get_contents($fileName); 88 | $contents = str_replace("[[SCRIPTS]]",$scripts,$contents); 89 | echo str_replace("[[TITLE]]",$title,$contents); 90 | } 91 | 92 | $result = MG::init(); 93 | if(isBot()){ 94 | //ob_start("ob_gzhandler"); 95 | Contents::outputPage(); 96 | }else if($result === null){ 97 | outputFile(".index.html"); 98 | } 99 | else{ 100 | //Log::output(MG::getSessionHash(),$result["message"]); 101 | //ob_start("ob_gzhandler"); 102 | header("Content-type: application/json"); 103 | header("Access-Control-Allow-Origin: *"); 104 | echo json_encode($result, JSON_UNESCAPED_UNICODE); 105 | } 106 | -------------------------------------------------------------------------------- /save/readme.txt: -------------------------------------------------------------------------------- 1 | このフォルダにローカルデータベース「.local.db」が作成されます 2 | 書き込み権限を入れてください --------------------------------------------------------------------------------