admin.php 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980
  1. <?php
  2. if (!defined('HTMLY')) die('HTMLy');
  3. use \Michelf\MarkdownExtra;
  4. // Return username.ini value
  5. function user($key, $user = null)
  6. {
  7. $value = 'config/users/' . $user . '.ini';
  8. static $_config = array();
  9. if (file_exists($value)) {
  10. $_config = parse_ini_file($value, true);
  11. if (!empty($_config[$key])) {
  12. return $_config[$key];
  13. }
  14. }
  15. }
  16. // Update the user
  17. function update_user($userName, $password, $role, $mfa_secret)
  18. {
  19. $file = 'config/users/' . $userName . '.ini';
  20. if (file_exists($file)) {
  21. file_put_contents($file, "password = " . password_hash($password, PASSWORD_DEFAULT) . "\n" .
  22. "encryption = password_hash\n" .
  23. "role = " . $role . "\n" .
  24. "mfa_secret = " . $mfa_secret . "\n", LOCK_EX);
  25. return true;
  26. }
  27. return false;
  28. }
  29. // Create user
  30. function create_user($userName, $password, $role)
  31. {
  32. $file = 'config/users/' . $userName . '.ini';
  33. if (file_exists($file)) {
  34. return false;
  35. } else {
  36. file_put_contents($file, "password = " . password_hash($password, PASSWORD_DEFAULT) . "\n" .
  37. "encryption = password_hash\n" .
  38. "role = " . $role . "\n" .
  39. "mfa_secret = disabled\n", LOCK_EX);
  40. return true;
  41. }
  42. }
  43. // Create a session
  44. function session($user, $pass)
  45. {
  46. $user_file = 'config/users/' . $user . '.ini';
  47. if (!file_exists($user_file)) {
  48. return $str = '<div class="error-message"><ul><li class="alert alert-danger">' . i18n('Invalid_Error') . '</li></ul></div>';
  49. }
  50. $user_enc = user('encryption', $user);
  51. $user_pass = user('password', $user);
  52. $user_role = user('role', $user);
  53. $mfa = user('mfa_secret', $user);
  54. if(is_null($user_enc) || is_null($user_pass) || is_null($user_role)) {
  55. return $str = '<div class="error-message"><ul><li class="alert alert-danger">' . i18n('Invalid_Error') . '</li></ul></div>';
  56. }
  57. if ($user_enc == "password_hash") {
  58. if (password_verify($pass, $user_pass)) {
  59. if (session_status() == PHP_SESSION_NONE) session_start();
  60. if (password_needs_rehash($user_pass, PASSWORD_DEFAULT)) {
  61. update_user($user, $pass, $user_role, $mfa);
  62. }
  63. $_SESSION[site_url()]['user'] = $user;
  64. header('location: admin');
  65. } else {
  66. return $str = '<div class="error-message"><ul><li class="alert alert-danger">' . i18n('Invalid_Error') . '</li></ul></div>';
  67. }
  68. } else if (old_password_verify($pass, $user_enc, $user_pass)) {
  69. if (session_status() == PHP_SESSION_NONE) session_start();
  70. update_user($user, $pass, $user_role, $mfa);
  71. $_SESSION[site_url()]['user'] = $user;
  72. header('location: admin');
  73. } else {
  74. return $str = '<div class="error-message"><ul><li class="alert alert-danger">' . i18n('Invalid_Error') . '</li></ul></div>';
  75. }
  76. }
  77. function old_password_verify($pass, $user_enc, $user_pass)
  78. {
  79. $password = (strlen($user_enc) > 0 && $user_enc !== 'clear' && $user_enc !== 'none') ? hash($user_enc, $pass) : $pass;
  80. return ($password === $user_pass);
  81. }
  82. // Generate csrf token
  83. function generate_csrf_token()
  84. {
  85. $_SESSION[site_url()]['csrf_token'] = sha1(microtime(true) . mt_rand(10000, 90000));
  86. }
  87. // Get csrf token
  88. function get_csrf()
  89. {
  90. if (!isset($_SESSION[site_url()]['csrf_token']) || empty($_SESSION[site_url()]['csrf_token'])) {
  91. generate_csrf_token();
  92. }
  93. return $_SESSION[site_url()]['csrf_token'];
  94. }
  95. // Check the csrf token
  96. function is_csrf_proper($csrf_token)
  97. {
  98. if ($csrf_token == get_csrf()) {
  99. return true;
  100. }
  101. return false;
  102. }
  103. // Clean URLs
  104. function remove_accent($str)
  105. {
  106. if (is_null(config('transliterate.slug')) || config('transliterate.slug') !== 'false') {
  107. return URLify::downcode($str);
  108. }
  109. return $str;
  110. }
  111. // Add content
  112. function add_content($title, $tag, $url, $content, $user, $draft, $category, $type, $description = null, $media = null, $dateTime = null, $autoSave = null, $oldfile = null, $field = null)
  113. {
  114. if (!is_null($autoSave)) {
  115. $draft = 'draft';
  116. }
  117. $tag = explode(',', preg_replace("/\s*,\s*/", ",", rtrim($tag, ',')));
  118. $tag = array_filter(array_unique($tag));
  119. $tagslang = "content/data/tags.lang";
  120. if (file_exists($tagslang)) {
  121. $taglang = array_flip(unserialize(file_get_contents($tagslang)));
  122. $tflip = array_intersect_key($taglang, array_flip($tag));
  123. $post_tag = array();
  124. $post_tagmd = array();
  125. foreach ($tag as $t) {
  126. if (array_key_exists($t, $tflip)) {
  127. foreach ($tflip as $tfp => $tf){
  128. if($t == $tfp) {
  129. $post_tag[] = $tf;
  130. $post_tagmd[] = $tfp;
  131. }
  132. }
  133. } else {
  134. $post_tag[] = $t;
  135. $post_tagmd[] = $t;
  136. }
  137. }
  138. $post_tag = safe_tag(implode(',', $post_tag));
  139. $post_tagmd = safe_html(implode(',', $post_tagmd));
  140. } else {
  141. $post_tag = safe_tag(implode(',', $tag));
  142. $post_tagmd = safe_html(implode(',', $tag));
  143. }
  144. $post_date = date('Y-m-d-H-i-s', strtotime($dateTime));
  145. $post_title = safe_html($title);
  146. $post_tag = strtolower(preg_replace(array('/[^a-zA-Z0-9,. \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($post_tag)));
  147. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  148. $category = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($category)));
  149. $description = safe_html($description);
  150. $post_t = explode(',', $post_tag);
  151. $pret_t = explode(',', $post_tagmd);
  152. $tags = tag_cloud(true);
  153. $timestamp = date('YmdHis');
  154. $combine = array_combine($pret_t, $post_t);
  155. $inter = array_intersect_key($tags, array_flip($post_t));
  156. $newtag = array();
  157. foreach ($combine as $tag => $v) {
  158. if (array_key_exists($v, $tags)) {
  159. foreach ($inter as $in => $i){
  160. if($v == $in) {
  161. $newtag[$v]= $tag;
  162. }
  163. }
  164. } else {
  165. $newtag[$v] = $tag;
  166. }
  167. }
  168. $post_tag = implode(',', array_keys($newtag));
  169. $posts = get_blog_posts();
  170. foreach ($posts as $index => $v) {
  171. $arr = explode('_', $v['basename']);
  172. if (strtolower($arr[2]) === strtolower($post_url . '.md')) {
  173. $post_url = $post_url .'-'. $timestamp;
  174. } else {
  175. $post_url = $post_url;
  176. }
  177. }
  178. if ($description !== null) {
  179. if (!empty($description)) {
  180. $post_description = "\n<!--d " . $description . " d-->";
  181. } else {
  182. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  183. }
  184. } else {
  185. $post_description = "";
  186. }
  187. if ($tag !== null) {
  188. $tagmd = "\n<!--tag " . $post_tagmd . " tag-->";
  189. } else {
  190. $tagmd = "";
  191. }
  192. if ($media!== null) {
  193. $post_media = "\n<!--" .$type. " " . preg_replace('/\s\s+/', ' ', strip_tags($media)) . " " .$type. "-->";
  194. } else {
  195. $post_media = "";
  196. }
  197. $customField = "";
  198. if (!empty($field)) {
  199. foreach ($field as $key => $val) {
  200. if (!empty($val)) {
  201. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  202. }
  203. }
  204. }
  205. $post_content = "<!--t " . $post_title . " t-->" . $post_description . $tagmd . $post_media . $customField . "\n\n" . $content;
  206. if (!empty($post_title) && !empty($post_tag) && !empty($post_url) && !empty($post_content)) {
  207. $filename = $post_date . '_' . $post_tag . '_' . $post_url . '.md';
  208. if (empty($draft)) {
  209. if (date('Y-m-d-H-i-s') >= $post_date) {
  210. $dir = 'content/' . $user . '/blog/' . $category. '/'.$type. '/';
  211. } else {
  212. $dir = 'content/' . $user . '/blog/' . $category. '/'.$type. '/scheduled/';
  213. }
  214. } else {
  215. $dir = 'content/' . $user . '/blog/' . $category. '/draft/';
  216. }
  217. if (!is_dir($dir)) {
  218. mkdir($dir, 0775, true);
  219. }
  220. $searchFile = "content/data/search.json";
  221. $search = array();
  222. $oldfile = $oldfile;
  223. $newfile = $dir . $filename;
  224. if ($oldfile !== $newfile && !is_null($autoSave)) {
  225. if (file_exists($oldfile)) {
  226. rename($oldfile, $newfile);
  227. if (config('fulltext.search') == "true") {
  228. if (file_exists($searchFile)) {
  229. $search = json_decode(file_get_data($searchFile), true);
  230. }
  231. $old_filename = pathinfo($oldfile, PATHINFO_FILENAME);
  232. $old_ex = explode('_', $old_filename);
  233. $old_url = $old_ex[2];
  234. $oKey = 'post_' . $old_url;
  235. $nKey = 'post_' . $post_url;
  236. if ($old_url != $post_url) {
  237. if (isset($search[$oKey])) {
  238. $arr = replace_key($search, $oKey, $nKey);
  239. $arr[$nKey] = $post_content;
  240. save_json_pretty($searchFile, $arr);
  241. }
  242. }
  243. }
  244. }
  245. } else {
  246. if (config('fulltext.search') == "true") {
  247. if (file_exists($searchFile)) {
  248. $search = json_decode(file_get_data($searchFile), true);
  249. }
  250. if (!isset($search['flock_fail'])) {
  251. $search['post_' . $post_url] = $post_content;
  252. save_json_pretty($searchFile, $search);
  253. }
  254. }
  255. }
  256. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  257. if (empty($draft)) {
  258. $draftFile = 'content/' . $user . '/blog/' . $category. '/draft/' . $filename;
  259. if (file_exists($draftFile)) {
  260. unlink($draftFile);
  261. }
  262. }
  263. save_tag_i18n($post_tag, $post_tagmd);
  264. rebuilt_cache('all');
  265. clear_post_cache($post_date, $post_tag, $post_url, $dir . $filename, $category, $type);
  266. if (!is_null($autoSave)) {
  267. return json_encode(array('message' => 'Auto Saved', 'file' => $newfile));
  268. }
  269. if (empty($draft)) {
  270. if (date('Y-m-d-H-i-s') >= $post_date) {
  271. $redirect = site_url() . 'admin/mine';
  272. } else {
  273. $redirect = site_url() . 'admin/scheduled';
  274. }
  275. } else {
  276. $redirect = site_url() . 'admin/draft';
  277. }
  278. header("Location: $redirect");
  279. }
  280. }
  281. // Edit content
  282. function edit_content($title, $tag, $url, $content, $oldfile, $revertPost, $publishDraft, $category, $type, $destination = null, $description = null, $date = null, $media = null, $autoSave = null, $field = null)
  283. {
  284. $tag = explode(',', preg_replace("/\s*,\s*/", ",", rtrim($tag, ',')));
  285. $tag = array_filter(array_unique($tag));
  286. $tagslang = "content/data/tags.lang";
  287. $newfile = '';
  288. $views = array();
  289. $viewsFile = "content/data/views.json";
  290. if (file_exists($tagslang)) {
  291. $taglang = array_flip(unserialize(file_get_contents($tagslang)));
  292. $tflip = array_intersect_key($taglang, array_flip($tag));
  293. $post_tag = array();
  294. $post_tagmd = array();
  295. foreach ($tag as $t) {
  296. if (array_key_exists($t, $tflip)) {
  297. foreach ($tflip as $tfp => $tf){
  298. if($t == $tfp) {
  299. $post_tag[] = $tf;
  300. $post_tagmd[] = $tfp;
  301. }
  302. }
  303. } else {
  304. $post_tag[] = $t;
  305. $post_tagmd[] = $t;
  306. }
  307. }
  308. $post_tag = safe_tag(implode(',', $post_tag));
  309. $post_tagmd = safe_html(implode(',', $post_tagmd));
  310. } else {
  311. $post_tag = safe_tag(implode(',', $tag));
  312. $post_tagmd = safe_html(implode(',', $tag));
  313. }
  314. $dir = explode('/', pathinfo($oldfile, PATHINFO_DIRNAME));
  315. $olddate = date('Y-m-d-H-i-s', strtotime($date));
  316. $post_title = safe_html($title);
  317. $post_tag = strtolower(preg_replace(array('/[^a-zA-Z0-9,. \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($post_tag)));
  318. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  319. $category = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($category)));
  320. $description = safe_html($description);
  321. $post_t = explode(',', $post_tag);
  322. $pret_t = explode(',', $post_tagmd);
  323. $tags = tag_cloud(true);
  324. $timestamp = date('YmdHis');
  325. $combine = array_combine($pret_t, $post_t);
  326. $inter = array_intersect_key($tags, array_flip($post_t));
  327. $newtag = array();
  328. foreach ($combine as $tag => $v) {
  329. if (array_key_exists($v, $tags)) {
  330. foreach ($inter as $in => $i){
  331. if($v == $in) {
  332. $newtag[$v]= $tag;
  333. }
  334. }
  335. } else {
  336. $newtag[$v] = $tag;
  337. }
  338. }
  339. $post_tag = implode(',', array_keys($newtag));
  340. if ($description !== null) {
  341. if (!empty($description)) {
  342. $post_description = "\n<!--d " . $description . " d-->";
  343. } else {
  344. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  345. }
  346. } else {
  347. $post_description = "";
  348. }
  349. if ($tag !== null) {
  350. $tagmd = "\n<!--tag " . $post_tagmd . " tag-->";
  351. } else {
  352. $tagmd = "";
  353. }
  354. if ($media !== null) {
  355. $post_media = "\n<!--" . $type . " " . preg_replace('/\s\s+/', ' ', strip_tags($media)) . " " . $type . "-->";
  356. } else {
  357. $post_media = "";
  358. }
  359. $customField = "";
  360. if (!empty($field)) {
  361. foreach ($field as $key => $val) {
  362. if (!empty($val)) {
  363. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  364. }
  365. }
  366. }
  367. $post_content = "<!--t " . $post_title . " t-->" . $post_description . $tagmd . $post_media . $customField . "\n\n" . $content;
  368. $dirBlog = $dir[0] . '/' . $dir[1] . '/' . $dir[2] . '/' . $category . '/' . $type . '/';
  369. $dirDraft = $dir[0] . '/' . $dir[1] . '/' . $dir[2] . '/' . $category . '/draft/';
  370. $dirScheduled = $dir[0] . '/' . $dir[1] . '/' . $dir[2] . '/' . $category . '/' . $type . '/scheduled/';
  371. if (!is_dir($dirBlog)) {
  372. mkdir($dirBlog, 0775, true);
  373. }
  374. if (!is_dir($dirDraft)) {
  375. mkdir($dirDraft, 0775, true);
  376. }
  377. if (!is_dir($dirScheduled)) {
  378. mkdir($dirScheduled, 0775, true);
  379. }
  380. if (!empty($post_title) && !empty($post_tag) && !empty($post_url) && !empty($post_content)) {
  381. if(!empty($revertPost) || !empty($publishDraft)) {
  382. if($dir[4] == 'draft') {
  383. if (date('Y-m-d-H-i-s') >= $olddate) {
  384. $newfile = $dirBlog . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  385. } else {
  386. $newfile = $dirScheduled . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  387. }
  388. } else {
  389. $newfile = $dirDraft . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  390. }
  391. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  392. unlink($oldfile);
  393. } else {
  394. if ($dir[3] === $category) {
  395. if($dir[4] == 'draft') {
  396. $newfile = $dirDraft . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  397. } else {
  398. if (date('Y-m-d-H-i-s') >= $olddate) {
  399. $newfile = $dirBlog . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  400. } else {
  401. $newfile = $dirScheduled . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  402. }
  403. }
  404. if ($oldfile === $newfile) {
  405. file_put_contents($oldfile, print_r($post_content, true), LOCK_EX);
  406. } else {
  407. rename($oldfile, $newfile);
  408. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  409. }
  410. } else {
  411. if($dir[4] == 'draft') {
  412. $newfile = $dirDraft . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  413. } else {
  414. if (date('Y-m-d-H-i-s') >= $olddate) {
  415. $newfile = $dirBlog . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  416. } else {
  417. $newfile = $dirScheduled . $olddate . '_' . $post_tag . '_' . $post_url . '.md';
  418. }
  419. }
  420. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  421. unlink($oldfile);
  422. }
  423. }
  424. if(!empty($publishDraft)) {
  425. $dt = $olddate;
  426. $t = str_replace('-', '', $dt);
  427. $time = new DateTime($t);
  428. $timestamp = $time->format("Y-m-d");
  429. } else {
  430. $fn = explode('_', pathinfo($oldfile, PATHINFO_FILENAME));
  431. $dt = $fn[0];
  432. $t = str_replace('-', '', $dt);
  433. $time = new DateTime($t);
  434. $timestamp = $time->format("Y-m-d");
  435. }
  436. // The post date
  437. $postdate = strtotime($timestamp);
  438. // The post URL
  439. if (permalink_type() == 'default') {
  440. $posturl = site_url() . date('Y/m', $postdate) . '/' . $post_url;
  441. } else {
  442. $posturl = site_url() . permalink_type() . '/' . $post_url;
  443. }
  444. save_tag_i18n($post_tag, $post_tagmd);
  445. rebuilt_cache('all');
  446. clear_post_cache($dt, $post_tag, $post_url, $oldfile, $category, $type);
  447. $searchFile = "content/data/search.json";
  448. $search = array();
  449. $old_filename = pathinfo($oldfile, PATHINFO_FILENAME);
  450. $old_ex = explode('_', $old_filename);
  451. $old_url = $old_ex[2];
  452. if ($old_url != $post_url) {
  453. $oKey = 'post_' . $old_url;
  454. $nKey = 'post_' . $post_url;
  455. if (file_exists($viewsFile)) {
  456. $views = json_decode(file_get_data($viewsFile), true);
  457. if (isset($views[$oKey])) {
  458. $arr = replace_key($views, $oKey, $nKey);
  459. save_json_pretty($viewsFile, $arr);
  460. }
  461. }
  462. if (config('fulltext.search') == "true") {
  463. if (file_exists($searchFile)) {
  464. $search = json_decode(file_get_data($searchFile), true);
  465. if (isset($search[$oKey])) {
  466. $arr = replace_key($search, $oKey, $nKey);
  467. $arr[$nKey] = $post_content;
  468. save_json_pretty($searchFile, $arr);
  469. }
  470. }
  471. }
  472. } else {
  473. if (config('fulltext.search') == "true") {
  474. if (file_exists($searchFile)) {
  475. $search = json_decode(file_get_data($searchFile), true);
  476. }
  477. if (!isset($search['flock_fail'])) {
  478. $search['post_' . $post_url] = $post_content;
  479. save_json_pretty($searchFile, $search);
  480. }
  481. }
  482. }
  483. if (!is_null($autoSave)) {
  484. return json_encode(array('message' => 'Auto Saved', 'file' => $newfile));
  485. }
  486. if ($destination == 'post') {
  487. if(!empty($revertPost)) {
  488. $drafturl = site_url() . 'admin/draft';
  489. header("Location: $drafturl");
  490. } else {
  491. if (date('Y-m-d-H-i-s') >= $olddate) {
  492. header("Location: $posturl");
  493. } else {
  494. $schurl = site_url() . 'admin/scheduled';
  495. header("Location: $schurl");
  496. }
  497. }
  498. } else {
  499. if(!empty($publishDraft)) {
  500. if (date('Y-m-d-H-i-s') >= $olddate) {
  501. header("Location: $posturl");
  502. } else {
  503. $schurl = site_url() . 'admin/scheduled';
  504. header("Location: $schurl");
  505. }
  506. } elseif (!empty($revertPost)) {
  507. $drafturl = site_url() . 'admin/draft';
  508. header("Location: $drafturl");
  509. } else {
  510. $redirect = site_url() . $destination;
  511. header("Location: $redirect");
  512. }
  513. }
  514. }
  515. }
  516. // Add static page
  517. function add_page($title, $url, $content, $draft, $description = null, $autoSave = null, $oldfile = null, $field = null)
  518. {
  519. if (!is_null($autoSave)) {
  520. $draft = 'draft';
  521. }
  522. $post_title = safe_html($title);
  523. $newfile = '';
  524. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  525. $description = safe_html($description);
  526. if ($description !== null) {
  527. if (!empty($description)) {
  528. $post_description = "\n<!--d " . $description . " d-->";
  529. } else {
  530. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  531. }
  532. } else {
  533. $post_description = "";
  534. }
  535. $posts = get_static_pages();
  536. $timestamp = date('YmdHis');
  537. foreach ($posts as $index => $v) {
  538. $m_url = explode('.', $v['filename']);
  539. if (isset($m_url[1])) {
  540. $b_url = $m_url[1] . '.md';
  541. } else {
  542. $b_url = $v['basename'];
  543. }
  544. if (strtolower($b_url) === strtolower($post_url . '.md')) {
  545. $post_url = $post_url .'-'. $timestamp;
  546. } else {
  547. $post_url = $post_url;
  548. }
  549. }
  550. $customField = "";
  551. if (!empty($field)) {
  552. foreach ($field as $key => $val) {
  553. if (!empty($val)) {
  554. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  555. }
  556. }
  557. }
  558. $post_content = '<!--t ' . $post_title . ' t-->' . $post_description . $customField . "\n\n" . $content;
  559. if (!empty($post_title) && !empty($post_url) && !empty($post_content)) {
  560. $filename = $post_url . '.md';
  561. $dir = 'content/static/';
  562. $dirDraft = 'content/static/draft/';
  563. if (empty($draft)) {
  564. if (!is_dir($dir)) {
  565. mkdir($dir, 0775, true);
  566. }
  567. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  568. $draftFile = $dirDraft . $filename;
  569. if (file_exists($draftFile)) {
  570. unlink($draftFile);
  571. }
  572. } else {
  573. if (!is_dir($dirDraft)) {
  574. mkdir($dirDraft, 0775, true);
  575. }
  576. $oldfile = $oldfile;
  577. $newfile = $dirDraft . $filename;
  578. if ($oldfile !== $newfile && !is_null($autoSave)) {
  579. if (file_exists($oldfile)) {
  580. rename($oldfile, $newfile);
  581. }
  582. }
  583. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  584. }
  585. rebuilt_cache('all');
  586. clear_page_cache($post_url);
  587. if (!is_null($autoSave)) {
  588. return json_encode(array('message' => 'Auto Saved', 'file' => $newfile));
  589. }
  590. if (empty($draft)) {
  591. $redirect = site_url() . 'admin/pages';
  592. header("Location: $redirect");
  593. } else {
  594. $redirect = site_url() . 'admin/draft';
  595. header("Location: $redirect");
  596. }
  597. }
  598. }
  599. // Add static sub page
  600. function add_sub_page($title, $url, $content, $static, $draft, $description = null, $autoSave = null, $oldfile = null, $field = null)
  601. {
  602. if (!is_null($autoSave)) {
  603. $draft = 'draft';
  604. }
  605. $post = find_page($static);
  606. $newfile = '';
  607. $static = pathinfo($post['current']->md, PATHINFO_FILENAME);
  608. $post_title = safe_html($title);
  609. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  610. $description = safe_html($description);
  611. if ($description !== null) {
  612. if (!empty($description)) {
  613. $post_description = "\n<!--d " . $description . " d-->";
  614. } else {
  615. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  616. }
  617. } else {
  618. $post_description = "";
  619. }
  620. $posts = get_static_subpages($post['current']->slug);
  621. $timestamp = date('YmdHis');
  622. foreach ($posts as $index => $v) {
  623. $m_url = explode('.', $v['filename']);
  624. if (isset($m_url[1])) {
  625. $b_url = $m_url[1] . '.md';
  626. } else {
  627. $b_url = $v['basename'];
  628. }
  629. if (strtolower($b_url) === strtolower($post_url . '.md')) {
  630. $post_url = $post_url .'-'. $timestamp;
  631. } else {
  632. $post_url = $post_url;
  633. }
  634. }
  635. $customField = "";
  636. if (!empty($field)) {
  637. foreach ($field as $key => $val) {
  638. if (!empty($val)) {
  639. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  640. }
  641. }
  642. }
  643. $post_content = '<!--t ' . $post_title . ' t-->' . $post_description . $customField . "\n\n" . $content;
  644. if (!empty($post_title) && !empty($post_url) && !empty($post_content)) {
  645. $filename = $post_url . '.md';
  646. $dir = 'content/static/' . $static . '/';
  647. $dirDraft = 'content/static/' . $static . '/draft/';
  648. if (empty($draft)) {
  649. if (!is_dir($dir)) {
  650. mkdir($dir, 0775, true);
  651. }
  652. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  653. $draftFile = $dirDraft . $filename;
  654. if (file_exists($draftFile)) {
  655. unlink($draftFile);
  656. }
  657. } else {
  658. if (!is_dir($dirDraft)) {
  659. mkdir($dirDraft, 0775, true);
  660. }
  661. $oldfile = $oldfile;
  662. $newfile = $dirDraft . $filename;
  663. if ($oldfile !== $newfile && !is_null($autoSave)) {
  664. if (file_exists($oldfile)) {
  665. rename($oldfile, $newfile);
  666. }
  667. }
  668. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  669. }
  670. if (!is_null($autoSave)) {
  671. return json_encode(array('message' => 'Auto Saved', 'file' => $newfile));
  672. }
  673. rebuilt_cache('all');
  674. clear_page_cache($post_url);
  675. $redirect = site_url() . 'admin/pages';
  676. header("Location: $redirect");
  677. }
  678. }
  679. // Edit static page and sub page
  680. function edit_page($title, $url, $content, $oldfile, $revertPage, $publishDraft, $destination = null, $description = null, $static = null, $autoSave = null, $field = null)
  681. {
  682. $dir = pathinfo($oldfile, PATHINFO_DIRNAME);
  683. $fn = explode('.', pathinfo($oldfile, PATHINFO_FILENAME));
  684. if (isset($fn[1])) {
  685. $num = $fn[0] . '.';
  686. } else {
  687. $num = null;
  688. }
  689. $newfile = '';
  690. $views = array();
  691. $viewsFile = "content/data/views.json";
  692. $post_title = safe_html($title);
  693. $pUrl = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  694. $post_url = $num . $pUrl;
  695. $description = safe_html($description);
  696. if ($description !== null) {
  697. if (!empty($description)) {
  698. $post_description = "\n<!--d " . $description . " d-->";
  699. } else {
  700. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  701. }
  702. } else {
  703. $post_description = "";
  704. }
  705. $customField = "";
  706. if (!empty($field)) {
  707. foreach ($field as $key => $val) {
  708. if (!empty($val)) {
  709. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  710. }
  711. }
  712. }
  713. $post_content = '<!--t ' . $post_title . ' t-->' . $post_description . $customField . "\n\n" . $content;
  714. if (!empty($post_title) && !empty($post_url) && !empty($post_content)) {
  715. if(!empty($revertPage)) {
  716. $dirDraft = $dir . '/draft';
  717. if (!is_dir($dirDraft)) {
  718. mkdir($dirDraft, 0775, true);
  719. }
  720. $newfile = $dirDraft . '/' . $post_url . '.md';
  721. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  722. if (empty($static)) {
  723. $old = pathinfo($oldfile, PATHINFO_FILENAME);
  724. if(is_dir($dir . '/' . $old)) {
  725. rename($dir . '/' . $old, $dir . '/' . $post_url);
  726. }
  727. }
  728. unlink($oldfile);
  729. } elseif (!empty($publishDraft)) {
  730. $newfile = dirname($dir) . '/' . $post_url . '.md';
  731. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  732. if (empty($static)) {
  733. $old = pathinfo($oldfile, PATHINFO_FILENAME);
  734. if(is_dir(dirname($dir) . '/' . $old)) {
  735. rename(dirname($dir) . '/' . $old, dirname($dir) . '/' . $post_url);
  736. }
  737. }
  738. unlink($oldfile);
  739. } else {
  740. $newfile = $dir . '/' . $post_url . '.md';
  741. if ($oldfile === $newfile) {
  742. file_put_contents($oldfile, print_r($post_content, true), LOCK_EX);
  743. } else {
  744. rename($oldfile, $newfile);
  745. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  746. if (empty($static)) {
  747. $old = pathinfo($oldfile, PATHINFO_FILENAME);
  748. if(is_dir($dir . '/' . $old)) {
  749. rename($dir . '/' . $old, $dir . '/' . $post_url);
  750. }
  751. }
  752. }
  753. }
  754. $cl = explode('.', $post_url);
  755. if (isset($cl[1])) {
  756. $pu = $cl[1];
  757. } else {
  758. $pu = $post_url;
  759. }
  760. $old_filename = pathinfo($oldfile, PATHINFO_FILENAME);
  761. $old_ex = explode('.', $old_filename);
  762. if (isset($old_ex[1])) {
  763. $old_url = $old_ex[1];
  764. } else {
  765. $old_url = $old_filename;
  766. }
  767. rebuilt_cache('all');
  768. clear_page_cache($post_url);
  769. if (!empty($static)) {
  770. $posturl = site_url() . $static .'/'. $pu;
  771. if ($old_url != $pu) {
  772. if (file_exists($viewsFile)) {
  773. $views = json_decode(file_get_data($viewsFile), true);
  774. $oKey = 'subpage_' . $static . '.' . $old_url;
  775. $nKey = 'subpage_' . $static . '.' . $pu;
  776. if (isset($views[$oKey])) {
  777. $arr = replace_key($views, $oKey, $nKey);
  778. save_json_pretty($viewsFile, $arr);
  779. }
  780. }
  781. }
  782. } else {
  783. $posturl = site_url() . $pu;
  784. if ($old_url != $pu) {
  785. if (file_exists($viewsFile)) {
  786. $views = json_decode(file_get_data($viewsFile), true);
  787. $oKey = 'page_' . $old_url;
  788. $nKey = 'page_' . $pu;
  789. if (isset($views[$oKey])) {
  790. $arr = replace_key($views, $oKey, $nKey);
  791. save_json_pretty($viewsFile, $arr);
  792. }
  793. }
  794. $sPage = find_subpage($pu);
  795. if (!empty($sPage)) {
  796. foreach ($sPage as $sp) {
  797. if (file_exists($viewsFile)) {
  798. $views = json_decode(file_get_data($viewsFile), true);
  799. $oKey = 'subpage_' . $old_url . '.' . $sp->slug;
  800. $nKey = 'subpage_' . $pu . '.' . $sp->slug;
  801. if (isset($views[$oKey])) {
  802. $arr = replace_key($views, $oKey, $nKey);
  803. save_json_pretty($viewsFile, $arr);
  804. }
  805. }
  806. }
  807. }
  808. }
  809. }
  810. if (!is_null($autoSave)) {
  811. return json_encode(array('message' => 'Auto Saved', 'file' => $newfile));
  812. }
  813. if ($destination == 'post') {
  814. if(!empty($revertPage)) {
  815. $drafturl = site_url() . 'admin/draft';
  816. header("Location: $drafturl");
  817. } else {
  818. header("Location: $posturl");
  819. }
  820. } else {
  821. $redirect = site_url() . $destination;
  822. header("Location: $redirect");
  823. }
  824. }
  825. }
  826. // Add category
  827. function add_category($title, $url, $content, $description = null)
  828. {
  829. $post_title = safe_html($title);
  830. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  831. $description = safe_html($description);
  832. if ($description !== null) {
  833. if (!empty($description)) {
  834. $post_description = "\n<!--d " . $description . " d-->";
  835. } else {
  836. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  837. }
  838. } else {
  839. $post_description = "";
  840. }
  841. $post_content = '<!--t ' . $post_title . ' t-->' . $post_description . "\n\n" . $content;
  842. if (!empty($post_title) && !empty($post_url) && !empty($post_content)) {
  843. $filename = $post_url . '.md';
  844. $dir = 'content/data/category/';
  845. if (is_dir($dir)) {
  846. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  847. } else {
  848. mkdir($dir, 0775, true);
  849. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  850. }
  851. rebuilt_cache('all');
  852. clear_page_cache($post_url);
  853. $redirect = site_url() . 'admin/categories';
  854. header("Location: $redirect");
  855. }
  856. }
  857. // Edit category
  858. function edit_category($title, $url, $content, $oldfile, $destination = null, $description = null)
  859. {
  860. $dir = pathinfo($oldfile, PATHINFO_DIRNAME);
  861. $post_title = safe_html($title);
  862. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  863. $description = safe_html($description);
  864. if ($description !== null) {
  865. if (!empty($description)) {
  866. $post_description = "\n<!--d " . $description . " d-->";
  867. } else {
  868. $post_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  869. }
  870. } else {
  871. $post_description = "";
  872. }
  873. $post_content = '<!--t ' . $post_title . ' t-->' . $post_description . "\n\n" . $content;
  874. if (!empty($post_title) && !empty($post_url) && !empty($post_content)) {
  875. $newfile = $dir . '/' . $post_url . '.md';
  876. if (!is_dir($dir)) {
  877. mkdir($dir, 0775, true);
  878. }
  879. if ($oldfile === $newfile) {
  880. file_put_contents($oldfile, print_r($post_content, true), LOCK_EX);
  881. } else {
  882. if (file_exists($oldfile)) {
  883. rename($oldfile, $newfile);
  884. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  885. } else {
  886. file_put_contents($newfile, print_r($post_content, true), LOCK_EX);
  887. }
  888. }
  889. rename_category_folder($post_url, $oldfile);
  890. rebuilt_cache('all');
  891. if ($destination == 'post') {
  892. header("Location: $posturl");
  893. } else {
  894. $redirect = site_url() . $destination;
  895. header("Location: $redirect");
  896. }
  897. }
  898. }
  899. // Edit user profile
  900. function edit_profile($title, $content, $user, $description = null, $image = null, $field = null)
  901. {
  902. $description = safe_html($description);
  903. if ($description !== null) {
  904. if (!empty($description)) {
  905. $profile_description = "\n<!--d " . $description . " d-->";
  906. } else {
  907. $profile_description = "\n<!--d " . get_description(MarkdownExtra::defaultTransform($content)) . " d-->";
  908. }
  909. } else {
  910. $profile_description = "";
  911. }
  912. if ($image !== null) {
  913. $avatar = "\n<!--image " . $image . " image-->";
  914. } else {
  915. $avatar = "";
  916. }
  917. $customField = "";
  918. if (!empty($field)) {
  919. foreach ($field as $key => $val) {
  920. if (!empty($val)) {
  921. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  922. }
  923. }
  924. }
  925. $user_title = safe_html($title);
  926. $user_content = '<!--t ' . $user_title . ' t-->' . $profile_description . $avatar . $customField . "\n\n" . $content;
  927. if (!empty($user_title) && !empty($user_content)) {
  928. $dir = 'content/' . $user . '/';
  929. $filename = 'content/' . $user . '/author.md';
  930. if (is_dir($dir)) {
  931. file_put_contents($filename, print_r($user_content, true), LOCK_EX);
  932. } else {
  933. mkdir($dir, 0775, true);
  934. file_put_contents($filename, print_r($user_content, true), LOCK_EX);
  935. }
  936. rebuilt_cache('all');
  937. $redirect = site_url() . 'author/' . $user;
  938. header("Location: $redirect");
  939. }
  940. }
  941. // Edit homepage
  942. function edit_frontpage($title, $content, $field = null)
  943. {
  944. $customField = "";
  945. if (!empty($field)) {
  946. foreach ($field as $key => $val) {
  947. if (!empty($val)) {
  948. $customField .= "\n<!--" . $key . ' ' . preg_replace('/\s+/', ' ', trim($val)) . ' ' . $key . "-->";
  949. }
  950. }
  951. }
  952. $front_title = safe_html($title);
  953. $front_content = '<!--t ' . $front_title . ' t-->' . $customField . "\n\n" . $content;
  954. if (!empty($front_title) && !empty($front_content)) {
  955. $dir = 'content/data/frontpage';
  956. $filename = 'content/data/frontpage/frontpage.md';
  957. if (is_dir($dir)) {
  958. file_put_contents($filename, print_r($front_content, true), LOCK_EX);
  959. } else {
  960. mkdir($dir, 0775, true);
  961. file_put_contents($filename, print_r($front_content, true), LOCK_EX);
  962. }
  963. rebuilt_cache('all');
  964. $redirect = site_url();
  965. header("Location: $redirect");
  966. }
  967. }
  968. // Delete blog post
  969. function delete_post($file, $destination)
  970. {
  971. if (!login())
  972. return null;
  973. $deleted_content = $file;
  974. $user = $_SESSION[site_url()]['user'];
  975. $role = user('role', $user);
  976. $arr = explode('/', $file);
  977. // realpath resolves all traversal operations like ../
  978. $realFilePath = realpath($file);
  979. // realpath returns an empty string if the file does not exist
  980. if ($realFilePath == '') {
  981. return;
  982. }
  983. // get the current project working directory
  984. $cwd = getcwd();
  985. // content directory relative to the current project working directory
  986. $contentDir = $cwd . DIRECTORY_SEPARATOR . 'content';
  987. // if the file path does not start with $contentDir, it means its accessing
  988. // files in folders other than content
  989. if (strpos($realFilePath, $contentDir) !== 0) {
  990. return;
  991. }
  992. // Get cache file
  993. $info = pathinfo($file);
  994. $fn = explode('_', $info['basename']);
  995. $dr = explode('/', $info['dirname']);
  996. clear_post_cache($fn[0], $fn[1], str_replace('.md', '', $fn[2]), $file, $dr[3], $dr[4]);
  997. if (!empty($deleted_content)) {
  998. if ($user === $arr[1] || $role === 'editor' || $role === 'admin') {
  999. unlink($deleted_content);
  1000. rebuilt_cache('all');
  1001. if ($destination == 'post') {
  1002. $redirect = site_url();
  1003. header("Location: $redirect");
  1004. } else {
  1005. $redirect = site_url() . $destination;
  1006. header("Location: $redirect");
  1007. }
  1008. }
  1009. }
  1010. }
  1011. // Delete static page
  1012. function delete_page($file, $destination)
  1013. {
  1014. if (!login())
  1015. return null;
  1016. $deleted_content = $file;
  1017. $user = $_SESSION[site_url()]['user'];
  1018. $role = user('role', $user);
  1019. // realpath resolves all traversal operations like ../
  1020. $realFilePath = realpath($file);
  1021. // realpath returns an empty string if the file does not exist
  1022. if ($realFilePath == '') {
  1023. return;
  1024. }
  1025. // get the current project working directory
  1026. $cwd = getcwd();
  1027. // content directory relative to the current project working directory
  1028. $contentDir = $cwd . DIRECTORY_SEPARATOR . 'content';
  1029. // if the file path does not start with $contentDir, it means its accessing
  1030. // files in folders other than content
  1031. if (strpos($realFilePath, $contentDir) !== 0) {
  1032. return;
  1033. }
  1034. if (!empty($menu)) {
  1035. foreach (glob('cache/page/*.cache', GLOB_NOSORT) as $file) {
  1036. unlink($file);
  1037. }
  1038. } else {
  1039. clear_page_cache(pathinfo($file, PATHINFO_BASENAME));
  1040. }
  1041. if (!empty($deleted_content)) {
  1042. if ($role === 'editor' || $role === 'admin') {
  1043. unlink($deleted_content);
  1044. rebuilt_cache('all');
  1045. if ($destination == 'post') {
  1046. $redirect = site_url();
  1047. header("Location: $redirect");
  1048. } else {
  1049. $redirect = site_url() . $destination;
  1050. header("Location: $redirect");
  1051. }
  1052. }
  1053. }
  1054. }
  1055. // Find draft.
  1056. function find_draft($year, $month, $name)
  1057. {
  1058. $posts = get_draft_posts();
  1059. foreach ($posts as $index => $v) {
  1060. $arr = explode('_', $v['basename']);
  1061. if (strpos($arr[0], "$year-$month") !== false && strtolower($arr[2]) === strtolower($name . '.md') || strtolower($arr[2]) === strtolower($name . '.md')) {
  1062. // Use the get_posts method to return
  1063. // a properly parsed object
  1064. $ar = get_posts($posts, $index + 1, 1);
  1065. $nx = get_posts($posts, $index, 1);
  1066. $pr = get_posts($posts, $index + 2, 1);
  1067. if ($index == 0) {
  1068. if (isset($pr[0])) {
  1069. return array(
  1070. 'current' => $ar[0],
  1071. 'prev' => $pr[0]
  1072. );
  1073. } else {
  1074. return array(
  1075. 'current' => $ar[0],
  1076. 'prev' => null
  1077. );
  1078. }
  1079. } elseif (count($posts) == $index + 1) {
  1080. return array(
  1081. 'current' => $ar[0],
  1082. 'next' => $nx[0]
  1083. );
  1084. } else {
  1085. return array(
  1086. 'current' => $ar[0],
  1087. 'next' => $nx[0],
  1088. 'prev' => $pr[0]
  1089. );
  1090. }
  1091. }
  1092. }
  1093. }
  1094. // Return draft list
  1095. function get_draft($profile, $page, $perpage)
  1096. {
  1097. $user = $_SESSION[site_url()]['user'];
  1098. $role = user('role', $user);
  1099. $posts = get_draft_posts();
  1100. $tmp = array();
  1101. foreach ($posts as $index => $v) {
  1102. $str = explode('/', $v['dirname']);
  1103. if (strtolower($profile) === strtolower($str[1]) || $role === 'editor' || $role === 'admin') {
  1104. $tmp[] = $v;
  1105. }
  1106. }
  1107. if (empty($tmp)) {
  1108. return $tmp;
  1109. }
  1110. return $tmp = array(get_posts($tmp, $page, $perpage), count($tmp));
  1111. }
  1112. // Return draft static page.
  1113. function find_draft_page($static = null)
  1114. {
  1115. $posts = get_draft_pages();
  1116. $tmp = array();
  1117. $counter = config('views.counter');
  1118. if ($counter == 'true') {
  1119. $viewsFile = "content/data/views.json";
  1120. if (file_exists($viewsFile)) {
  1121. $views = json_decode(file_get_contents($viewsFile), true);
  1122. }
  1123. }
  1124. if (!empty($posts)) {
  1125. foreach ($posts as $index => $v) {
  1126. if (stripos($v['basename'], $static . '.md') !== false) {
  1127. $post = new stdClass;
  1128. // The static page URL
  1129. $fn = explode('.', $v['filename']);
  1130. if (isset($fn[1])) {
  1131. $url = $fn[1];
  1132. } else {
  1133. $url= $v['filename'];
  1134. }
  1135. $post->url = site_url() . $url;
  1136. $post->file = $v['dirname'] . '/' . $v['basename'];
  1137. $post->lastMod = strtotime(date('Y-m-d H:i:s', filemtime($post->file)));
  1138. $post->md = $v['basename'];
  1139. $post->slug = $url;
  1140. $post->parent = null;
  1141. $post->parentSlug = null;
  1142. // Get the contents and convert it to HTML
  1143. $content = file_get_contents($post->file);
  1144. // Extract the title and body
  1145. $post->title = get_content_tag('t', $content, 'Untitled static page: ' . format_date($post->lastMod, 'l, j F Y, H:i'));
  1146. // Get the contents and convert it to HTML
  1147. $post->body = MarkdownExtra::defaultTransform(remove_html_comments($content));
  1148. if ($counter == 'true') {
  1149. $post->views = get_views('page_' . $post->slug, $views);
  1150. } else {
  1151. $post->views = null;
  1152. }
  1153. $post->description = get_content_tag("d", $content, get_description($post->body));
  1154. $word_count = str_word_count(strip_tags($post->body));
  1155. $post->readTime = ceil($word_count / 200);
  1156. $tmp[] = $post;
  1157. }
  1158. }
  1159. }
  1160. return $tmp;
  1161. }
  1162. // Return draft static subpage.
  1163. function find_draft_subpage($static = null, $sub_static = null)
  1164. {
  1165. $posts = get_draft_subpages($static);
  1166. $tmp = array();
  1167. $counter = config('views.counter');
  1168. if ($counter == 'true') {
  1169. $viewsFile = "content/data/views.json";
  1170. if (file_exists($viewsFile)) {
  1171. $views = json_decode(file_get_contents($viewsFile), true);
  1172. }
  1173. }
  1174. if (!empty($posts)) {
  1175. foreach ($posts as $index => $v) {
  1176. if (stripos($v['basename'], $sub_static . '.md') !== false) {
  1177. $post = new stdClass;
  1178. $fd = str_replace('content/static/', '', dirname($v['dirname']));
  1179. $pr = explode('.', $fd);
  1180. if (isset($pr[1])) {
  1181. $ps = $pr[1];
  1182. } else {
  1183. $ps = $fd;
  1184. }
  1185. // The static page URL
  1186. $fn = explode('.', $v['filename']);
  1187. if (isset($fn[1])) {
  1188. $url = $fn[1];
  1189. } else {
  1190. $url = $v['filename'];
  1191. }
  1192. $post->parent = $fd;
  1193. $post->parentSlug = $ps;
  1194. $post->url = site_url() . $ps . "/" . $url;
  1195. $post->file = $v['dirname'] . '/' . $v['basename'];
  1196. $post->lastMod = strtotime(date('Y-m-d H:i:s', filemtime($post->file)));
  1197. $post->md = $v['basename'];
  1198. $post->slug = $url;
  1199. // Get the contents and convert it to HTML
  1200. $content = file_get_contents($post->file);
  1201. // Extract the title and body
  1202. $post->title = get_content_tag('t', $content, 'Untitled static subpage: ' . format_date($post->lastMod, 'l, j F Y, H:i'));
  1203. // Get the contents and convert it to HTML
  1204. $post->body = MarkdownExtra::defaultTransform(remove_html_comments($content));
  1205. if ($counter == 'true') {
  1206. $post->views = get_views('subpage_' . $post->parentSlug .'.'. $post->slug, $views);
  1207. } else {
  1208. $post->views = null;
  1209. }
  1210. $post->description = get_content_tag("d", $content, get_description($post->body));
  1211. $word_count = str_word_count(strip_tags($post->body));
  1212. $post->readTime = ceil($word_count / 200);
  1213. $tmp[] = $post;
  1214. }
  1215. }
  1216. }
  1217. return $tmp;
  1218. }
  1219. // Find scheduled post.
  1220. function find_scheduled($year, $month, $name)
  1221. {
  1222. $posts = get_scheduled_posts();
  1223. foreach ($posts as $index => $v) {
  1224. $arr = explode('_', $v['basename']);
  1225. if (strpos($arr[0], "$year-$month") !== false && strtolower($arr[2]) === strtolower($name . '.md') || strtolower($arr[2]) === strtolower($name . '.md')) {
  1226. // Use the get_posts method to return
  1227. // a properly parsed object
  1228. $ar = get_posts($posts, $index + 1, 1);
  1229. $nx = get_posts($posts, $index, 1);
  1230. $pr = get_posts($posts, $index + 2, 1);
  1231. if ($index == 0) {
  1232. if (isset($pr[0])) {
  1233. return array(
  1234. 'current' => $ar[0],
  1235. 'prev' => $pr[0]
  1236. );
  1237. } else {
  1238. return array(
  1239. 'current' => $ar[0],
  1240. 'prev' => null
  1241. );
  1242. }
  1243. } elseif (count($posts) == $index + 1) {
  1244. return array(
  1245. 'current' => $ar[0],
  1246. 'next' => $nx[0]
  1247. );
  1248. } else {
  1249. return array(
  1250. 'current' => $ar[0],
  1251. 'next' => $nx[0],
  1252. 'prev' => $pr[0]
  1253. );
  1254. }
  1255. }
  1256. }
  1257. }
  1258. // Return scheduled list
  1259. function get_scheduled($profile, $page, $perpage)
  1260. {
  1261. $user = $_SESSION[site_url()]['user'];
  1262. $role = user('role', $user);
  1263. $posts = get_scheduled_posts();
  1264. $tmp = array();
  1265. foreach ($posts as $index => $v) {
  1266. $str = explode('/', $v['dirname']);
  1267. if (strtolower($profile) === strtolower($str[1]) || $role === 'editor' || $role === 'admin') {
  1268. $tmp[] = $v;
  1269. }
  1270. }
  1271. if (empty($tmp)) {
  1272. return $tmp;
  1273. }
  1274. return $tmp = array(get_posts($tmp, $page, $perpage), count($tmp));
  1275. }
  1276. // Import RSS feed
  1277. function migrate($title, $time, $tags, $content, $url, $user, $source)
  1278. {
  1279. $post_date = date('Y-m-d-H-i-s', $time);
  1280. $post_title = safe_html($title);
  1281. $pt = safe_tag($tags);
  1282. $post_tag = strtolower(preg_replace(array('/[^a-zA-Z0-9,. \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($pt)));
  1283. $post_tagmd = preg_replace(array('/[^a-zA-Z0-9,. \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', ' ', ''), $pt);
  1284. $post_tag = rtrim($post_tag, ',');
  1285. $post_tagmd = rtrim($post_tagmd, ',');
  1286. $post_url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($url)));
  1287. if (!empty($source)) {
  1288. $post_content = '<!--t ' . $post_title . ' t-->' . "\n" . '<!--tag ' . $post_tagmd . ' tag-->' . "\n\n" . $content . "\n\n" . 'Source: <a target="_blank" href="' . $source . '">' . $title . '</a>';
  1289. } else {
  1290. $post_content = '<!--t ' . $post_title . ' t-->' . "\n" . '<!--tag ' . $post_tagmd . ' tag-->' . "\n\n" . $content;
  1291. }
  1292. if (!empty($post_title) && !empty($post_tag) && !empty($post_url) && !empty($post_content)) {
  1293. $filename = $post_date . '_' . $post_tag . '_' . $post_url . '.md';
  1294. $dir = 'content/' . $user . '/blog/uncategorized/post/';
  1295. if (is_dir($dir)) {
  1296. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  1297. } else {
  1298. mkdir($dir, 0775, true);
  1299. file_put_contents($dir . $filename, print_r($post_content, true), LOCK_EX);
  1300. }
  1301. save_tag_i18n($post_tag, $post_tagmd);
  1302. $redirect = site_url() . 'admin/clear-cache';
  1303. header("Location: $redirect");
  1304. }
  1305. }
  1306. // Fetch RSS feed
  1307. function get_feed($feed_url, $credit)
  1308. {
  1309. $source = file_get_contents($feed_url);
  1310. $feed = new SimpleXmlElement($source);
  1311. if (!empty($feed->channel->item)) {
  1312. foreach ($feed->channel->item as $entry) {
  1313. $descriptionA = $entry->children('content', true);
  1314. $descriptionB = $entry->description;
  1315. if (!empty($descriptionA)) {
  1316. $content = $descriptionA;
  1317. } elseif (!empty($descriptionB)) {
  1318. $content = preg_replace('#<br\s*/?>#i', "\n", $descriptionB);
  1319. } else {
  1320. return $str = '<li>' . i18n('Cannot_read_feed_content') . '</li>';
  1321. }
  1322. $time = new DateTime($entry->pubDate);
  1323. $timestamp = $time->format("Y-m-d H:i:s");
  1324. $time = strtotime($timestamp);
  1325. $tags = $entry->category;
  1326. $title = rtrim($entry->title, ' \,\.\-');
  1327. $title = ltrim($title, ' \,\.\-');
  1328. $user = $_SESSION[site_url()]['user'];
  1329. $url = strtolower(preg_replace(array('/[^a-zA-Z0-9 \-\p{L}]/u', '/[ -]+/', '/^-|-$/'), array('', '-', ''), remove_accent($title)));
  1330. if ($credit == 'yes') {
  1331. $source = $entry->link;
  1332. } else {
  1333. $source = null;
  1334. }
  1335. migrate($title, $time, $tags, $content, $url, $user, $source);
  1336. }
  1337. } else {
  1338. return $str = '<li>' . i18n('Unknown_feed_format') . '</li>';
  1339. }
  1340. }
  1341. // return tag safe string
  1342. function safe_tag($string)
  1343. {
  1344. $tags = array();
  1345. $string = preg_replace('/[\s-]+/', ' ', $string);
  1346. $string = explode(',', $string);
  1347. $string = array_map('trim', $string);
  1348. foreach ($string as $str) {
  1349. $tags[] = $str;
  1350. }
  1351. $string = implode(',', $tags);
  1352. $string = preg_replace('/[\s_]/', '-', $string);
  1353. return $string;
  1354. }
  1355. // Create Zip files
  1356. function Zip($source, $destination, $include_dir = false)
  1357. {
  1358. if (!extension_loaded('zip') || !file_exists($source)) {
  1359. return false;
  1360. }
  1361. if (file_exists($destination)) {
  1362. unlink($destination);
  1363. }
  1364. $zip = new ZipArchive();
  1365. if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
  1366. return false;
  1367. }
  1368. if (is_dir($source) === true) {
  1369. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
  1370. foreach ($files as $file) {
  1371. $file = str_replace('\\', '/', $file);
  1372. // Ignore "." and ".." folders
  1373. if (in_array(substr($file, strrpos($file, '/') + 1), array('.', '..')))
  1374. continue;
  1375. if (is_dir($file) === true) {
  1376. $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
  1377. } elseif (is_file($file) === true) {
  1378. $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
  1379. }
  1380. }
  1381. } elseif (is_file($source) === true) {
  1382. $zip->addFromString(basename($source), file_get_contents($source));
  1383. }
  1384. return $zip->close();
  1385. }
  1386. // Return toolbar
  1387. function toolbar()
  1388. {
  1389. $user = $_SESSION[site_url()]['user'];
  1390. $role = user('role', $user);
  1391. $base = site_url();
  1392. $toolbar = '';
  1393. $toolbar .= <<<EOF
  1394. <link href="{$base}system/resources/css/toolbar.css?v=1" rel="stylesheet" />
  1395. <script src="{$base}system/resources/js/toolbar.js"></script>
  1396. EOF;
  1397. $toolbar .= '<div id="toolbar"><label for="htmly-menu-toggle" id="htmly-menu-button">☰ ' . i18n('Menu') . '</label><input type="checkbox" id="htmly-menu-toggle"><div id="htmly-menu"><ul>';
  1398. $toolbar .= '<li class="tb-admin"><a href="' . $base . 'admin">' . i18n('Admin') . '</a></li>';
  1399. $toolbar .= '<li class="tb-addcontent"><a href="' . $base . 'admin/content">' . i18n('Add_content') . '</a></li>';
  1400. if ($role === 'editor' || $role === 'admin') {
  1401. $toolbar .= '<li class="tb-posts"><a href="' . $base . 'admin/posts">' . i18n('Posts') . '</a></li>';
  1402. if (config('views.counter') == 'true') {
  1403. $toolbar .= '<li class="tb-popular"><a href="' . $base . 'admin/popular">' . i18n('Popular') . '</a></li>';
  1404. }
  1405. $toolbar .= '<li class="tb-mine"><a href="' . $base . 'admin/pages">' . i18n('Pages') . '</a></li>';
  1406. }
  1407. $toolbar .= '<li class="tb-draft"><a href="' . $base . 'admin/scheduled">' . i18n('Scheduled') . '</a></li>';
  1408. $toolbar .= '<li class="tb-draft"><a href="' . $base . 'admin/draft">' . i18n('Draft') . '</a></li>';
  1409. if ($role === 'editor' || $role === 'admin') {
  1410. $toolbar .= '<li class="tb-categories"><a href="' . $base . 'admin/categories">' . i18n('Categories') . '</a></li>';
  1411. $toolbar .= '<li class="tb-import"><a href="' . $base . 'admin/menu">' . i18n('Menu') . '</a></li>';
  1412. }
  1413. if ($role === 'admin') {
  1414. $toolbar .= '<li class="tb-config"><a href="' . $base . 'admin/config">' . i18n('Config') . '</a></li>';
  1415. $toolbar .= '<li class="tb-config"><a href="' . $base . 'admin/themes">' . i18n('themes') . '</a></li>';
  1416. $toolbar .= '<li class="tb-backup"><a href="' . $base . 'admin/backup">' . i18n('Backup') . '</a></li>';
  1417. $toolbar .= '<li class="tb-update"><a href="' . $base . 'admin/update">' . i18n('Update') . '</a></li>';
  1418. }
  1419. if ($role === 'editor' || $role === 'admin') {
  1420. $toolbar .= '<li class="tb-clearcache"><a href="' . $base . 'admin/clear-cache">' . i18n('Clear_cache') . '</a></li>';
  1421. }
  1422. $toolbar .= '<li class="tb-editprofile"><a href="' . $base . 'edit/profile">' . i18n('Edit_profile') . '</a></li>';
  1423. $toolbar .= '<li class="tb-logout"><a href="' . $base . 'logout">' . i18n('Logout') . '</a></li>';
  1424. $toolbar .= '</ul></div></div>';
  1425. echo $toolbar;
  1426. }
  1427. // save the i18n tag
  1428. function save_tag_i18n($tag,$tagDisplay)
  1429. {
  1430. $dir = 'content/data/';
  1431. if (!is_dir($dir)) {
  1432. mkdir($dir, 0775, true);
  1433. }
  1434. $filename = "content/data/tags.lang";
  1435. $tags = array();
  1436. $tmp = array();
  1437. $views = array();
  1438. $tt = explode(',', rtrim($tag, ','));
  1439. $tl = explode(',', rtrim($tagDisplay, ','));
  1440. $tags = array_combine($tt,$tl);
  1441. if (file_exists($filename)) {
  1442. $views = unserialize(file_get_contents($filename));
  1443. foreach ($tags as $key => $val) {
  1444. if (isset($views[$key])) {
  1445. $views[$key] = $val;
  1446. } else {
  1447. $views[$key] = $val;
  1448. }
  1449. }
  1450. } else {
  1451. $views = $tags;
  1452. }
  1453. $tmp = serialize($views);
  1454. file_put_contents($filename, print_r($tmp, true), LOCK_EX);
  1455. }
  1456. function clear_post_cache($post_date, $post_tag, $post_url, $filename, $category, $type)
  1457. {
  1458. $b = str_replace('/', '#', site_path() . '/');
  1459. $c = explode(',', $post_tag);
  1460. $t = explode('-', $post_date);
  1461. // Delete post default permalink
  1462. $p = 'cache/page/' . $b . $t[0] . '#' . $t[1] . '#' . $post_url . '.cache';
  1463. if (file_exists($p)) {
  1464. unlink($p);
  1465. }
  1466. // Delete post permalink
  1467. $pp = 'cache/page/' . $b . 'post#' . $post_url . '.cache';
  1468. if (file_exists($pp)) {
  1469. unlink($pp);
  1470. }
  1471. // Delete homepage
  1472. $yd = 'cache/page/' . $b . '.cache';
  1473. if (file_exists($yd)) {
  1474. unlink($yd);
  1475. }
  1476. foreach (glob('cache/page/' . $b . '~*.cache', GLOB_NOSORT) as $file) {
  1477. unlink($file);
  1478. }
  1479. // Delete year
  1480. $yd = 'cache/page/' . $b . 'archive#' . $t[0] . '.cache';
  1481. if (file_exists($yd)) {
  1482. unlink($yd);
  1483. }
  1484. foreach (glob('cache/page/' . $b . 'archive#' . $t[0] . '~*.cache', GLOB_NOSORT) as $file) {
  1485. unlink($file);
  1486. }
  1487. // Delete year-month
  1488. $yd = 'cache/page/' . $b . 'archive#' . $t[0] . '-' . $t[1] . '.cache';
  1489. if (file_exists($yd)) {
  1490. unlink($yd);
  1491. }
  1492. foreach (glob('cache/page/' . $b . 'archive#' . $t[0] . '-' . $t[1] . '~*.cache', GLOB_NOSORT) as $file) {
  1493. unlink($file);
  1494. }
  1495. // Delete year-month-day
  1496. $yd = 'cache/page/' . $b . 'archive#' . $t[0] . '-' . $t[1] . '-' . $t[2] . '.cache';
  1497. if (file_exists($yd)) {
  1498. unlink($yd);
  1499. }
  1500. foreach (glob('cache/page/' . $b . 'archive#' . $t[0] . '-' . $t[1] . '-' . $t[2] . '~*.cache', GLOB_NOSORT) as $file) {
  1501. unlink($file);
  1502. }
  1503. // Delete tag
  1504. foreach ($c as $tag) {
  1505. $yd = 'cache/page/' . $b . 'tag#' . $tag . '.cache';
  1506. if (file_exists($yd)) {
  1507. unlink($yd);
  1508. }
  1509. foreach (glob('cache/page/' . $b . 'tag#' . $tag . '~*.cache', GLOB_NOSORT) as $file) {
  1510. unlink($file);
  1511. }
  1512. }
  1513. // Delete search
  1514. foreach (glob('cache/page/' . $b . 'search#*.cache', GLOB_NOSORT) as $file) {
  1515. unlink($file);
  1516. }
  1517. // Delete category
  1518. $cc = 'cache/page/' . $b . 'category#' . $category . '.cache';
  1519. if (file_exists($cc)) {
  1520. unlink($cc);
  1521. }
  1522. foreach (glob('cache/page/' . $b . 'category#' . $category . '~*.cache', GLOB_NOSORT) as $file) {
  1523. unlink($file);
  1524. }
  1525. // Delete type
  1526. $tp = 'cache/page/' . $b . 'type#' . $type . '.cache';
  1527. if (file_exists($tp)) {
  1528. unlink($tp);
  1529. }
  1530. foreach (glob('cache/page/' . $b . 'type#' . $type . '~*.cache', GLOB_NOSORT) as $file) {
  1531. unlink($file);
  1532. }
  1533. // Get cache post author
  1534. $arr = pathinfo($filename, PATHINFO_DIRNAME);
  1535. $x = explode('/', $arr);
  1536. // Delete author post list cache
  1537. $a = 'cache/page/' . $b . 'author#' . $x[1] . '.cache';
  1538. if (file_exists($a)) {
  1539. unlink($a);
  1540. }
  1541. foreach (glob('cache/page/' . $b . 'author#' . $x[1] . '~*.cache', GLOB_NOSORT) as $file) {
  1542. unlink($file);
  1543. }
  1544. }
  1545. function clear_page_cache($url)
  1546. {
  1547. $b = str_replace('/', '#', site_path() . '/');
  1548. $p = 'cache/page/' . $b . $url . '.cache';
  1549. if (file_exists($p)) {
  1550. unlink($p);
  1551. }
  1552. }
  1553. function clear_cache()
  1554. {
  1555. foreach (glob('cache/page/*.cache', GLOB_NOSORT) as $file) {
  1556. unlink($file);
  1557. }
  1558. }
  1559. function valueMaker($value)
  1560. {
  1561. if (is_string($value))
  1562. return htmlspecialchars($value);
  1563. if ($value === true)
  1564. return "true";
  1565. if ($value === false)
  1566. return "false";
  1567. if ($value == false)
  1568. return "0";
  1569. return (string)$value;
  1570. }
  1571. function replace_key($arr, $oldkey, $newkey)
  1572. {
  1573. if(array_key_exists($oldkey, $arr)) {
  1574. $keys = array_keys($arr);
  1575. $keys[array_search($oldkey, $keys)] = $newkey;
  1576. return array_combine($keys, $arr);
  1577. }
  1578. return $arr;
  1579. }
  1580. // rename category folder
  1581. function rename_category_folder($new_name, $old_file)
  1582. {
  1583. $old_name = str_replace('.md', '', basename($old_file));
  1584. $dir = get_category_folder();
  1585. foreach ($dir as $index => $v) {
  1586. if (stripos($v, '/' . $old_name . '/') !== false) {
  1587. $str = explode('/', $v);
  1588. $old_folder = $str[0] . '/' . $str[1] . '/' . $str[2] . '/' . $old_name . '/';
  1589. $new_folder = $str[0] . '/' . $str[1] . '/' . $str[2] . '/' . $new_name . '/';
  1590. rename($old_folder, $new_folder);
  1591. }
  1592. }
  1593. }
  1594. // reorder the static page
  1595. function reorder_pages($pages = null)
  1596. {
  1597. $i = 1;
  1598. $arr = array();
  1599. $dir = 'content/static/';
  1600. foreach ($pages as $p) {
  1601. $fn = pathinfo($p, PATHINFO_FILENAME);
  1602. $num = str_pad($i, 2, 0, STR_PAD_LEFT);
  1603. $arr = explode('.' , $fn);
  1604. if (isset($arr[1])) {
  1605. rename ($dir . $p, $dir . $num . '.' . $arr[1] . '.md');
  1606. if (is_dir($dir . $fn)) {
  1607. rename($dir . $fn, $dir . $num . '.' . $arr[1]);
  1608. }
  1609. } else {
  1610. rename($dir . $p, $dir . $num . '.' . $fn . '.md');
  1611. if (is_dir($dir . $fn)) {
  1612. rename($dir . $fn, $dir . $num . '.' . $fn);
  1613. }
  1614. }
  1615. $i++;
  1616. }
  1617. rebuilt_cache();
  1618. }
  1619. // reorder the subpage
  1620. function reorder_subpages($subpages = null)
  1621. {
  1622. $i = 1;
  1623. $arr = array();
  1624. $dir = 'content/static/';
  1625. foreach ($subpages as $sp) {
  1626. $dn = $dir . pathinfo($sp, PATHINFO_DIRNAME) . '/';
  1627. $fn = pathinfo($sp, PATHINFO_FILENAME);
  1628. $num = str_pad($i, 2, 0, STR_PAD_LEFT);
  1629. $arr = explode('.' , $fn);
  1630. if (isset($arr[1])) {
  1631. rename ($dir . $sp, $dn . $num . '.' . $arr[1] . '.md');
  1632. } else {
  1633. rename($dir . $sp, $dn . $num . '.' . $fn . '.md');
  1634. }
  1635. $i++;
  1636. }
  1637. rebuilt_cache();
  1638. }
  1639. // Return image gallery in pager.
  1640. function image_gallery($images, $page = 1, $perpage = 0)
  1641. {
  1642. if (empty($images)) {
  1643. $images = scan_images();
  1644. }
  1645. $tmp = '';
  1646. $pagination = has_pagination(count($images), $perpage, $page);
  1647. $images = array_slice($images, ($page - 1) * $perpage, $perpage);
  1648. $tmp .= '<div class="cover-container">';
  1649. foreach ($images as $index => $v) {
  1650. $tmp .= '<div class="cover-item"><img loading="lazy" class="img-thumbnail the-img" src="' . site_url() . $v['dirname'] . '/'. $v['basename'].'"></div>';
  1651. }
  1652. $tmp .= '</div><br><div class="row">';
  1653. if (!empty($pagination['prev'])) {
  1654. $prev = $page - 1;
  1655. $tmp .= '<a class="btn btn-primary left" style="margin: .25rem;" href="#'. $prev .'" onclick="loadImages(' . $prev . ')">← '. i18n('Prev') .'</a>';
  1656. }
  1657. if (!empty($pagination['next'])) {
  1658. $next = $page + 1;
  1659. $tmp .= '<a class="btn btn-primary right" style="margin: .25rem;" href="#'. $next .'" onclick="loadImages(' . $next . ')">'. i18n('Next') .' →</a>';
  1660. }
  1661. $tmp .= '</div>';
  1662. return $tmp;
  1663. }
  1664. function authorized ($data = null)
  1665. {
  1666. if (login()) {
  1667. if (is_null($data)) {
  1668. return false;
  1669. }
  1670. $user = $_SESSION[site_url()]['user'];
  1671. $role = user('role', $user);
  1672. if (isset($data->author)) {
  1673. if ($user === $data->author || $role === 'editor' || $role === 'admin') {
  1674. return true;
  1675. } else {
  1676. return false;
  1677. }
  1678. } else {
  1679. if ($role === 'editor' || $role === 'admin') {
  1680. return true;
  1681. } else {
  1682. return false;
  1683. }
  1684. }
  1685. }
  1686. }
  1687. // Add search index
  1688. function add_search_index($id, $content)
  1689. {
  1690. $dir = 'content/data/';
  1691. if (!is_dir($dir)) {
  1692. mkdir($dir, 0775, true);
  1693. }
  1694. $filename = "content/data/search.json";
  1695. $search = array();
  1696. if (file_exists($filename)) {
  1697. $search = json_decode(file_get_data($filename), true);
  1698. }
  1699. if (isset($search['flock_fail'])) {
  1700. return;
  1701. } else {
  1702. if (!isset($search[$id])) {
  1703. $search[$id] = $content;
  1704. save_json_pretty($filename, $search);
  1705. }
  1706. }
  1707. }