1:    2:    3:    4:    5:    6:    7:    8:    9:   10:   11:   12:   13:   14:   15:   16:   17:   18:   19:   20:   21:   22:   23:   24:   25:   26:   27:   28:   29:   30:   31:   32:   33:   34:   35:   36:   37:   38:   39:   40:   41:   42:   43:   44:   45:   46:   47:   48:   49:   50:   51:   52:   53:   54:   55:   56:   57:   58:   59:   60:   61:   62:   63:   64:   65:   66:   67:   68:   69:   70:   71:   72:   73:   74:   75:   76:   77:   78:   79:   80:   81:   82:   83:   84:   85:   86:   87:   88:   89:   90:   91:   92:   93:   94:   95:   96:   97:   98:   99:  100:  101:  102:  103:  104:  105:  106:  107:  108:  109:  110:  111:  112:  113:  114:  115:  116:  117:  118:  119:  120:  121:  122:  123:  124:  125:  126:  127:  128:  129:  130:  131:  132:  133:  134:  135:  136:  137:  138:  139:  140:  141:  142:  143:  144:  145:  146:  147:  148:  149:  150:  151:  152:  153:  154:  155:  156:  157:  158:  159:  160:  161:  162:  163:  164:  165:  166:  167:  168:  169:  170:  171:  172:  173:  174:  175:  176:  177:  178:  179:  180:  181:  182:  183:  184:  185:  186:  187:  188:  189:  190:  191:  192:  193:  194:  195:  196:  197:  198:  199:  200:  201:  202:  203:  204:  205:  206:  207:  208:  209:  210:  211:  212:  213:  214:  215:  216:  217:  218:  219:  220:  221:  222:  223:  224:  225:  226:  227:  228:  229:  230:  231:  232:  233:  234:  235:  236:  237:  238:  239:  240:  241:  242:  243:  244:  245:  246:  247:  248:  249:  250:  251:  252:  253:  254:  255:  256:  257:  258:  259:  260:  261:  262:  263:  264:  265:  266:  267:  268:  269:  270:  271:  272:  273:  274:  275:  276:  277:  278:  279:  280:  281:  282:  283:  284:  285:  286:  287:  288:  289:  290:  291:  292:  293:  294:  295:  296:  297:  298:  299:  300:  301:  302:  303:  304:  305:  306:  307:  308:  309:  310:  311:  312:  313:  314:  315:  316:  317:  318:  319:  320:  321:  322:  323:  324:  325:  326:  327:  328:  329:  330:  331:  332:  333:  334:  335:  336:  337:  338:  339:  340:  341:  342:  343:  344:  345:  346:  347:  348:  349:  350:  351:  352:  353:  354:  355:  356:  357:  358:  359:  360:  361:  362:  363:  364:  365:  366:  367:  368:  369:  370:  371:  372:  373:  374:  375:  376:  377:  378:  379:  380:  381:  382:  383:  384:  385:  386:  387:  388:  389:  390:  391:  392:  393:  394:  395:  396:  397:  398:  399:  400:  401:  402:  403:  404:  405:  406:  407:  408:  409:  410:  411:  412:  413:  414:  415:  416:  417:  418:  419:  420:  421:  422:  423:  424:  425:  426:  427:  428:  429:  430:  431:  432:  433:  434:  435:  436:  437:  438:  439:  440:  441:  442:  443:  444:  445:  446:  447:  448:  449:  450:  451:  452:  453:  454:  455:  456:  457:  458:  459:  460:  461:  462:  463:  464:  465:  466:  467:  468:  469:  470:  471:  472:  473:  474:  475:  476:  477:  478:  479:  480:  481:  482:  483:  484:  485:  486:  487:  488:  489:  490:  491:  492:  493:  494:  495:  496:  497:  498:  499:  500:  501:  502:  503:  504:  505:  506:  507:  508:  509:  510:  511:  512:  513:  514:  515:  516:  517:  518:  519:  520:  521:  522:  523:  524:  525:  526:  527:  528:  529:  530:  531:  532:  533:  534:  535:  536:  537:  538:  539:  540:  541:  542:  543:  544:  545:  546:  547:  548:  549:  550:  551:  552:  553:  554:  555:  556:  557:  558:  559:  560:  561:  562:  563:  564:  565:  566:  567:  568:  569:  570:  571:  572:  573:  574:  575:  576:  577:  578:  579:  580:  581:  582:  583:  584:  585:  586:  587:  588:  589:  590:  591:  592:  593:  594:  595:  596:  597:  598:  599:  600:  601:  602:  603:  604:  605:  606:  607:  608:  609:  610:  611:  612:  613:  614:  615:  616:  617:  618:  619:  620:  621:  622:  623:  624:  625:  626:  627:  628:  629:  630:  631:  632:  633:  634:  635:  636:  637:  638:  639:  640:  641:  642:  643:  644:  645:  646:  647:  648:  649:  650:  651:  652:  653:  654:  655:  656:  657:  658:  659:  660:  661:  662:  663:  664:  665:  666:  667:  668:  669:  670:  671:  672:  673:  674:  675:  676:  677:  678:  679:  680:  681:  682:  683:  684:  685:  686:  687:  688:  689:  690:  691:  692:  693:  694:  695:  696:  697:  698:  699:  700:  701:  702:  703:  704:  705:  706:  707:  708:  709:  710:  711:  712:  713:  714:  715:  716:  717:  718:  719:  720:  721:  722:  723:  724:  725:  726:  727:  728:  729:  730:  731:  732:  733:  734:  735:  736:  737:  738:  739:  740:  741:  742:  743:  744:  745:  746:  747:  748:  749:  750:  751:  752:  753:  754:  755:  756:  757:  758:  759:  760:  761:  762:  763:  764:  765:  766:  767:  768:  769:  770:  771:  772:  773:  774:  775:  776:  777:  778:  779:  780:  781:  782:  783:  784:  785:  786:  787:  788:  789:  790:  791:  792:  793:  794:  795:  796:  797:  798:  799:  800:  801:  802:  803:  804:  805:  806:  807:  808:  809:  810:  811:  812:  813:  814:  815:  816:  817:  818:  819:  820:  821:  822:  823:  824:  825:  826:  827:  828:  829:  830:  831:  832:  833:  834:  835:  836:  837:  838:  839:  840:  841:  842:  843:  844:  845:  846:  847:  848:  849:  850:  851:  852:  853:  854:  855:  856:  857:  858:  859:  860:  861:  862:  863:  864:  865:  866:  867:  868:  869:  870:  871:  872:  873:  874:  875:  876:  877:  878:  879:  880:  881:  882:  883:  884:  885:  886:  887:  888:  889:  890:  891:  892:  893:  894:  895:  896:  897:  898:  899:  900:  901:  902:  903:  904:  905:  906:  907:  908:  909:  910:  911:  912:  913:  914:  915:  916:  917:  918:  919:  920:  921:  922:  923:  924:  925:  926:  927:  928:  929:  930:  931:  932:  933:  934:  935:  936:  937:  938:  939:  940:  941:  942:  943:  944:  945:  946:  947:  948:  949:  950:  951:  952:  953:  954:  955:  956:  957:  958:  959:  960:  961:  962:  963:  964:  965:  966:  967:  968:  969:  970:  971:  972:  973:  974:  975:  976:  977:  978:  979:  980:  981:  982:  983:  984:  985:  986:  987:  988:  989:  990:  991:  992:  993:  994:  995:  996:  997:  998:  999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194: 1195: 1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205: 1206: 1207: 1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234: 1235: 1236: 1237: 1238: 1239: 1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254: 1255: 1256: 1257: 1258: 1259: 1260: 1261: 1262: 1263: 1264: 1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290: 1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355: 1356: 1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364: 1365: 1366: 1367: 1368: 1369: 1370: 1371: 1372: 1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392: 1393: 1394: 1395: 1396: 1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414: 1415: 1416: 1417: 1418: 1419: 1420: 1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430: 1431: 1432: 1433: 1434: 1435: 1436: 1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458: 1459: 1460: 1461: 1462: 1463: 1464: 1465: 1466: 1467: 1468: 1469: 1470: 1471: 1472: 1473: 1474: 1475: 1476: 1477: 1478: 1479: 1480: 1481: 1482: 1483: 1484: 1485: 1486: 1487: 1488: 1489: 1490: 1491: 1492: 1493: 1494: 1495: 1496: 1497: 1498: 1499: 1500: 1501: 1502: 1503: 1504: 1505: 1506: 1507: 1508: 1509: 1510: 1511: 1512: 1513: 1514: 1515: 1516: 1517: 1518: 1519: 1520: 1521: 1522: 1523: 1524: 1525: 1526: 1527: 1528: 1529: 1530: 1531: 1532: 1533: 1534: 1535: 1536: 1537: 1538: 1539: 1540: 1541: 1542: 1543: 1544: 1545: 1546: 1547: 1548: 1549: 1550: 1551: 1552: 1553: 1554: 1555: 1556: 1557: 1558: 1559: 1560: 1561: 1562: 1563: 1564: 1565: 1566: 1567: 1568: 1569: 1570: 1571: 1572: 1573: 1574: 1575: 1576: 1577: 1578: 1579: 1580: 1581: 1582: 1583: 1584: 1585: 1586: 1587: 1588: 1589: 1590: 1591: 1592: 1593: 1594: 1595: 1596: 1597: 1598: 1599: 1600: 1601: 1602: 1603: 1604: 1605: 1606: 1607: 1608: 1609: 1610: 1611: 1612: 1613: 1614: 1615: 1616: 1617: 1618: 1619: 1620: 1621: 1622: 1623: 1624: 1625: 1626: 1627: 1628: 1629: 1630: 1631: 1632: 1633: 1634: 1635: 1636: 1637: 1638: 1639: 1640: 1641: 1642: 1643: 1644: 1645: 1646: 1647: 1648: 1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656: 1657: 1658: 1659: 1660: 1661: 1662: 1663: 1664: 1665: 1666: 1667: 1668: 1669: 1670: 1671: 1672: 1673: 1674: 1675: 1676: 1677: 1678: 1679: 1680: 1681: 1682: 1683: 1684: 1685: 1686: 1687: 1688: 1689: 1690: 1691: 1692: 1693: 1694: 1695: 1696: 1697: 1698: 1699: 1700: 1701: 1702: 1703: 1704: 1705: 1706: 1707: 1708: 1709: 1710: 1711: 1712: 1713: 1714: 1715: 1716: 1717: 1718: 1719: 1720: 1721: 1722: 1723: 1724: 1725: 1726: 1727: 1728: 1729: 1730: 1731: 1732: 1733: 1734: 1735: 1736: 1737: 1738: 1739: 1740: 1741: 1742: 1743: 1744: 1745: 1746: 1747: 1748: 1749: 1750: 1751: 1752: 1753: 1754: 1755: 1756: 1757: 1758: 1759: 1760: 1761: 1762: 1763: 1764: 1765: 1766: 1767: 1768: 1769: 1770: 1771: 1772: 1773: 1774: 1775: 1776: 1777: 1778: 1779: 1780: 1781: 1782: 1783: 1784: 1785: 1786: 1787: 1788: 1789: 1790: 1791: 1792: 1793: 1794: 1795: 1796: 1797: 1798: 1799: 1800: 1801: 1802: 1803: 1804: 1805: 1806: 1807: 1808: 1809: 1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817: 1818: 1819: 1820: 1821: 1822: 1823: 1824: 1825: 1826: 1827: 1828: 1829: 1830: 1831: 1832: 1833: 1834: 1835: 1836: 1837: 1838: 1839: 1840: 1841: 1842: 1843: 1844: 1845: 1846: 1847: 1848: 1849: 1850: 1851: 1852: 1853: 1854: 1855: 1856: 1857: 1858: 1859: 1860: 1861: 1862: 1863: 1864: 1865: 1866: 1867: 1868: 1869: 1870: 1871: 1872: 1873: 1874: 1875: 1876: 1877: 1878: 1879: 1880: 1881: 1882: 1883: 1884: 1885: 1886: 1887: 1888: 1889: 1890: 1891: 1892: 1893: 1894: 1895: 1896: 1897: 1898: 1899: 1900: 1901: 1902: 1903: 1904: 1905: 1906: 1907: 1908: 1909: 1910: 1911: 1912: 1913: 1914: 1915: 1916: 1917: 1918: 1919: 1920: 1921: 1922: 1923: 1924: 1925: 1926: 1927: 1928: 1929: 1930: 1931: 1932: 1933: 1934: 1935: 1936: 1937: 1938: 1939: 1940: 1941: 1942: 1943: 1944: 1945: 1946: 1947: 1948: 1949: 1950: 1951: 1952: 1953: 1954: 1955: 1956: 1957: 1958: 1959: 1960: 1961: 1962: 1963: 1964: 1965: 1966: 1967: 1968: 1969: 1970: 1971: 1972: 1973: 1974: 1975: 1976: 1977: 1978: 1979: 1980: 1981: 1982: 1983: 1984: 1985: 1986: 1987: 1988: 1989: 1990: 1991: 1992: 1993: 1994: 1995: 1996: 1997: 1998: 1999: 2000: 2001: 2002: 2003: 2004: 2005: 2006: 2007: 2008: 2009: 2010: 2011: 2012: 2013: 2014: 2015: 2016: 2017: 2018: 2019: 2020: 2021: 2022: 2023: 2024: 2025: 2026: 2027: 2028: 2029: 2030: 2031: 2032: 2033: 2034: 2035: 2036: 2037: 2038: 2039: 2040: 2041: 2042: 2043: 2044: 2045: 2046: 2047: 2048: 2049: 2050: 2051: 2052: 2053: 2054: 2055: 2056: 2057: 2058: 2059: 2060: 2061: 2062: 2063: 2064: 2065: 2066: 2067: 2068: 2069: 2070: 2071: 2072: 2073: 2074: 2075: 2076: 2077: 2078: 2079: 2080: 2081: 2082: 2083: 2084: 2085: 2086: 2087: 2088: 2089: 2090: 2091: 2092: 2093: 2094: 2095: 2096: 2097: 2098: 2099: 2100: 2101: 2102: 2103: 2104: 2105: 2106: 2107: 2108: 2109: 2110: 2111: 2112: 2113: 2114: 2115: 2116: 2117: 2118: 2119: 2120: 2121: 2122: 2123: 2124: 2125: 2126: 2127: 2128: 2129: 2130: 2131: 2132: 2133: 2134: 2135: 2136: 2137: 2138: 2139: 2140: 2141: 2142: 2143: 2144: 2145: 2146: 2147: 2148: 2149: 2150: 2151: 2152: 2153: 2154: 2155: 2156: 2157: 2158: 2159: 2160: 2161: 2162: 2163: 2164: 2165: 2166: 2167: 2168: 
<?php
if (!defined('SMF'))
    die('No direct access...');
function getServerVersions($checkFor)
{
    global $txt, $db_connection, $_PHPA, $smcFunc, $cache_accelerator, $cache_memcached, $cacheAPI, $modSettings;
    loadLanguage('Admin');
    $versions = array();
    
    if (in_array('gd', $checkFor) && function_exists('gd_info'))
    {
        $temp = gd_info();
        $versions['gd'] = array('title' => $txt['support_versions_gd'], 'version' => $temp['GD Version']);
    }
    
    if (in_array('imagemagick', $checkFor) && (class_exists('Imagick') || function_exists('MagickGetVersionString')))
    {
        if (class_exists('Imagick'))
        {
            $temp = New Imagick;
            $temp2 = $temp->getVersion();
            $im_version = $temp2['versionString'];
            $extension_version = 'Imagick ' . phpversion('Imagick');
        }
        else
        {
            $im_version = MagickGetVersionString();
            $extension_version = 'MagickWand ' . phpversion('MagickWand');
        }
        
        $im_version = str_replace(array('ImageMagick ', ' https://www.imagemagick.org'), '', $im_version);
        $versions['imagemagick'] = array('title' => $txt['support_versions_imagemagick'], 'version' => $im_version . ' (' . $extension_version . ')');
    }
    
    if (in_array('db_server', $checkFor))
    {
        db_extend();
        if (!isset($db_connection) || $db_connection === false)
            trigger_error('getServerVersions(): you need to be connected to the database in order to get its server version', E_USER_NOTICE);
        else
        {
            $versions['db_engine'] = array('title' => sprintf($txt['support_versions_db_engine'], $smcFunc['db_title']), 'version' => '');
            $versions['db_engine']['version'] = $smcFunc['db_get_vendor']();
            $versions['db_server'] = array('title' => sprintf($txt['support_versions_db'], $smcFunc['db_title']), 'version' => '');
            $versions['db_server']['version'] = $smcFunc['db_get_version']();
        }
    }
    
    $memcache_version = '???';
    if (!empty($cache_accelerator) && ($cache_accelerator == 'memcached' || $cache_accelerator == 'memcache') && !empty($cache_memcached) && !empty($cacheAPI))
        $memcache_version = $cacheAPI->getVersion();
    
    if (in_array('phpa', $checkFor) && isset($_PHPA))
        $versions['phpa'] = array('title' => 'ionCube PHP-Accelerator', 'version' => $_PHPA['VERSION']);
    if (in_array('apc', $checkFor) && extension_loaded('apc'))
        $versions['apc'] = array('title' => 'Alternative PHP Cache', 'version' => phpversion('apc'));
    if (in_array('memcache', $checkFor) && function_exists('memcache_set'))
        $versions['memcache'] = array('title' => 'Memcached', 'version' => $memcache_version);
    if (in_array('xcache', $checkFor) && function_exists('xcache_set'))
        $versions['xcache'] = array('title' => 'XCache', 'version' => XCACHE_VERSION);
    if (in_array('php', $checkFor))
        $versions['php'] = array('title' => 'PHP', 'version' => PHP_VERSION, 'more' => '?action=admin;area=serversettings;sa=phpinfo');
    if (in_array('server', $checkFor))
        $versions['server'] = array('title' => $txt['support_versions_server'], 'version' => $_SERVER['SERVER_SOFTWARE']);
    return $versions;
}
function getFileVersions(&$versionOptions)
{
    global $boarddir, $sourcedir, $settings, $tasksdir;
    
    $lang_dir = $settings['default_theme_dir'] . '/languages';
    $version_info = array(
        'file_versions' => array(),
        'default_template_versions' => array(),
        'template_versions' => array(),
        'default_language_versions' => array(),
        'tasks_versions' => array(),
    );
    
    if (!empty($versionOptions['include_ssi']) && file_exists($boarddir . '/SSI.php'))
    {
        $fp = fopen($boarddir . '/SSI.php', 'rb');
        $header = fread($fp, 4096);
        fclose($fp);
        
        if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
            $version_info['file_versions']['SSI.php'] = $match[1];
        
        else
            $version_info['file_versions']['SSI.php'] = '??';
    }
    
    if (!empty($versionOptions['include_subscriptions']) && file_exists($boarddir . '/subscriptions.php'))
    {
        $fp = fopen($boarddir . '/subscriptions.php', 'rb');
        $header = fread($fp, 4096);
        fclose($fp);
        
        if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
            $version_info['file_versions']['subscriptions.php'] = $match[1];
        
        else
            $version_info['file_versions']['subscriptions.php'] = '??';
    }
    
    $sources_dir = dir($sourcedir);
    while ($entry = $sources_dir->read())
    {
        if (substr($entry, -4) === '.php' && !is_dir($sourcedir . '/' . $entry) && $entry !== 'index.php')
        {
            
            $fp = fopen($sourcedir . '/' . $entry, 'rb');
            $header = fread($fp, 4096);
            fclose($fp);
            
            if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
                $version_info['file_versions'][$entry] = $match[1];
            
            else
                $version_info['file_versions'][$entry] = '??';
        }
    }
    $sources_dir->close();
    
    if (!empty($versionOptions['include_tasks']))
    {
        $tasks_dir = dir($tasksdir);
        while ($entry = $tasks_dir->read())
        {
            if (substr($entry, -4) === '.php' && !is_dir($tasksdir . '/' . $entry) && $entry !== 'index.php')
            {
                
                $fp = fopen($tasksdir . '/' . $entry, 'rb');
                $header = fread($fp, 4096);
                fclose($fp);
                
                if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
                    $version_info['tasks_versions'][$entry] = $match[1];
                
                else
                    $version_info['tasks_versions'][$entry] = '??';
            }
        }
        $tasks_dir->close();
    }
    
    $directories = array('default_template_versions' => $settings['default_theme_dir']);
    if ($settings['theme_id'] != 1)
        $directories += array('template_versions' => $settings['theme_dir']);
    foreach ($directories as $type => $dirname)
    {
        $this_dir = dir($dirname);
        while ($entry = $this_dir->read())
        {
            if (substr($entry, -12) == 'template.php' && !is_dir($dirname . '/' . $entry))
            {
                
                $fp = fopen($dirname . '/' . $entry, 'rb');
                $header = fread($fp, 768);
                fclose($fp);
                
                if (preg_match('~\*\s@version\s+(.+)[\s]{2}~i', $header, $match) == 1)
                    $version_info[$type][$entry] = $match[1];
                
                else
                    $version_info[$type][$entry] = '??';
            }
        }
        $this_dir->close();
    }
    
    $this_dir = dir($lang_dir);
    while ($entry = $this_dir->read())
    {
        if (substr($entry, -4) == '.php' && $entry != 'index.php' && !is_dir($lang_dir . '/' . $entry))
        {
            
            $fp = fopen($lang_dir . '/' . $entry, 'rb');
            $header = fread($fp, 768);
            fclose($fp);
            
            list ($name, $language) = explode('.', $entry);
            
            if (preg_match('~(?://|/\*)\s*Version:\s+(.+?);\s*' . preg_quote($name, '~') . '(?:[\s]{2}|\*/)~i', $header, $match) == 1)
                $version_info['default_language_versions'][$language][$name] = $match[1];
            
            else
                $version_info['default_language_versions'][$language][$name] = '??';
        }
    }
    $this_dir->close();
    
    if (!empty($versionOptions['sort_results']))
    {
        ksort($version_info['file_versions']);
        ksort($version_info['default_template_versions']);
        ksort($version_info['template_versions']);
        ksort($version_info['default_language_versions']);
        ksort($version_info['tasks_versions']);
        
        foreach ($version_info['default_language_versions'] as $language => $dummy)
            ksort($version_info['default_language_versions'][$language]);
    }
    return $version_info;
}
function updateSettingsFile($config_vars, $keep_quotes = null, $rebuild = false)
{
    
    
    static $mtime;
    
    if (empty($keep_quotes))
    {
        foreach ($config_vars as $var => $val)
        {
            if (is_string($val) && ($keep_quotes === false || strpos($val, '\'') === 0 && strrpos($val, '\'') === strlen($val) - 1))
                $config_vars[$var] = trim(stripcslashes($val), '\'');
        }
    }
    
    if (isset($config_vars['db_last_error']))
    {
        updateDbLastError($config_vars['db_last_error']);
        if (count($config_vars) === 1 && empty($rebuild))
            return true;
        
        $config_vars['db_last_error'] = 0;
    }
    
    if (!is_bool($rebuild))
        $rebuild = false;
    $mtime = isset($mtime) ? (int) $mtime : (defined('TIME_START') ? TIME_START : $_SERVER['REQUEST_TIME']);
    
    
    foreach (get_included_files() as $settingsFile)
        if (basename($settingsFile) === 'Settings.php')
            break;
    
    if (basename($settingsFile) !== 'Settings.php')
        $settingsFile = (!empty($GLOBALS['boarddir']) && @realpath($GLOBALS['boarddir']) ? $GLOBALS['boarddir'] : (!empty($_SERVER['SCRIPT_FILENAME']) ? dirname($_SERVER['SCRIPT_FILENAME']) : dirname(__DIR__))) . '/Settings.php';
    
    if (!file_exists($settingsFile))
        @touch($settingsFile);
    
    $last_settings_change = filemtime($settingsFile);
    
    $settings_vars = get_current_settings($mtime, $settingsFile);
    
    if (empty($settings_vars) && file_exists(dirname($settingsFile) . '/Settings_bak.php'))
        $settings_vars = get_current_settings($mtime, dirname($settingsFile) . '/Settings_bak.php');
    
    if ($settings_vars === false)
        return false;
    
    $new_settings_vars = array_merge($settings_vars, $config_vars);
    
    $utf8 = isset($GLOBALS['context']['utf8']) ? $GLOBALS['context']['utf8'] : (isset($GLOBALS['utf8']) ? $GLOBALS['utf8'] : (isset($settings_vars['db_character_set']) ? $settings_vars['db_character_set'] === 'utf8' : false));
    
    $settings_defs = array(
        array(
            'text' => implode("\n", array(
                '',
                '/**',
                ' * The settings file contains all of the basic settings that need to be present when a database/cache is not available.',
                ' *',
                ' * Simple Machines Forum (SMF)',
                ' *',
                ' * @package SMF',
                ' * @author Simple Machines https://www.simplemachines.org',
                ' * @copyright ' . SMF_SOFTWARE_YEAR . ' Simple Machines and individual contributors',
                ' * @license https://www.simplemachines.org/about/smf/license.php BSD',
                ' *',
                ' * @version ' . SMF_VERSION,
                ' */',
                '',
            )),
            'search_pattern' => '~/\*\*.*?@package\h+SMF\b.*?\*/\n{0,2}~s',
        ),
        'maintenance' => array(
            'text' => implode("\n", array(
                '',
                '########## Maintenance ##########',
                '/**',
                ' * The maintenance "mode"',
                ' * Set to 1 to enable Maintenance Mode, 2 to make the forum untouchable. (you\'ll have to make it 0 again manually!)',
                ' * 0 is default and disables maintenance mode.',
                ' *',
                ' * @var int 0, 1, 2',
                ' * @global int $maintenance',
                ' */',
            )),
            'default' => 0,
            'type' => 'integer',
        ),
        'mtitle' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Title for the Maintenance Mode message.',
                ' *',
                ' * @var string',
                ' * @global int $mtitle',
                ' */',
            )),
            'default' => 'Maintenance Mode',
            'type' => 'string',
        ),
        'mmessage' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Description of why the forum is in maintenance mode.',
                ' *',
                ' * @var string',
                ' * @global string $mmessage',
                ' */',
            )),
            'default' => 'Okay faithful users...we\'re attempting to restore an older backup of the database...news will be posted once we\'re back!',
            'type' => 'string',
        ),
        'mbname' => array(
            'text' => implode("\n", array(
                '',
                '########## Forum Info ##########',
                '/**',
                ' * The name of your forum.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'My Community',
            'type' => 'string',
        ),
        'language' => array(
            'text' => implode("\n", array(
                '/**',
                ' * The default language file set for the forum.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'english',
            'type' => 'string',
        ),
        'boardurl' => array(
            'text' => implode("\n", array(
                '/**',
                ' * URL to your forum\'s folder. (without the trailing /!)',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'http://127.0.0.1/smf',
            'type' => 'string',
        ),
        'webmaster_email' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Email address to send emails from. (like noreply@yourdomain.com.)',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'noreply@myserver.com',
            'type' => 'string',
        ),
        'cookiename' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Name of the cookie to set for authentication.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'SMFCookie11',
            'type' => 'string',
        ),
        'db_type' => array(
            'text' => implode("\n", array(
                '',
                '########## Database Info ##########',
                '/**',
                ' * The database type',
                ' * Default options: mysql, postgresql',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'mysql',
            'type' => 'string',
        ),
        'db_port' => array(
            'text' => implode("\n", array(
                '/**',
                ' * The database port',
                ' * 0 to use default port for the database type',
                ' *',
                ' * @var int',
                ' */',
            )),
            'default' => 0,
            'type' => 'integer',
        ),
        'db_server' => array(
            'text' => implode("\n", array(
                '/**',
                ' * The server to connect to (or a Unix socket)',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'localhost',
            'required' => true,
            'type' => 'string',
        ),
        'db_name' => array(
            'text' => implode("\n", array(
                '/**',
                ' * The database name',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'smf',
            'required' => true,
            'type' => 'string',
        ),
        'db_user' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Database username',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'root',
            'required' => true,
            'type' => 'string',
        ),
        'db_passwd' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Database password',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => '',
            'required' => true,
            'type' => 'string',
        ),
        'ssi_db_user' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Database user for when connecting with SSI',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => '',
            'type' => 'string',
        ),
        'ssi_db_passwd' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Database password for when connecting with SSI',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => '',
            'type' => 'string',
        ),
        'db_prefix' => array(
            'text' => implode("\n", array(
                '/**',
                ' * A prefix to put in front of your table names.',
                ' * This helps to prevent conflicts',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'smf_',
            'required' => true,
            'type' => 'string',
        ),
        'db_persist' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Use a persistent database connection',
                ' *',
                ' * @var bool',
                ' */',
            )),
            'default' => false,
            'type' => 'boolean',
        ),
        'db_error_send' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Send emails on database connection error',
                ' *',
                ' * @var bool',
                ' */',
            )),
            'default' => false,
            'type' => 'boolean',
        ),
        'db_mb4' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Override the default behavior of the database layer for mb4 handling',
                ' * null keep the default behavior untouched',
                ' *',
                ' * @var null|bool',
                ' */',
            )),
            'default' => null,
            'type' => array('NULL', 'boolean'),
        ),
        'cache_accelerator' => array(
            'text' => implode("\n", array(
                '',
                '########## Cache Info ##########',
                '/**',
                ' * Select a cache system. You want to leave this up to the cache area of the admin panel for',
                ' * proper detection of apc, memcached, output_cache, smf, or xcache',
                ' * (you can add more with a mod).',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => '',
            'type' => 'string',
        ),
        'cache_enable' => array(
            'text' => implode("\n", array(
                '/**',
                ' * The level at which you would like to cache. Between 0 (off) through 3 (cache a lot).',
                ' *',
                ' * @var int',
                ' */',
            )),
            'default' => 0,
            'type' => 'integer',
        ),
        'cache_memcached' => array(
            'text' => implode("\n", array(
                '/**',
                ' * This is only used for memcache / memcached. Should be a string of \'server:port,server:port\'',
                ' *',
                ' * @var array',
                ' */',
            )),
            'default' => '',
            'type' => 'string',
        ),
        'cachedir' => array(
            'text' => implode("\n", array(
                '/**',
                ' * This is only for the \'smf\' file cache system. It is the path to the cache directory.',
                ' * It is also recommended that you place this in /tmp/ if you are going to use this.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'dirname(__FILE__) . \'/cache\'',
            'raw_default' => true,
            'type' => 'string',
        ),
        'image_proxy_enabled' => array(
            'text' => implode("\n", array(
                '',
                '########## Image Proxy ##########',
                '# This is done entirely in Settings.php to avoid loading the DB while serving the images',
                '/**',
                ' * Whether the proxy is enabled or not',
                ' *',
                ' * @var bool',
                ' */',
            )),
            'default' => true,
            'type' => 'boolean',
        ),
        'image_proxy_secret' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Secret key to be used by the proxy',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'smfisawesome',
            'type' => 'string',
        ),
        'image_proxy_maxsize' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Maximum file size (in KB) for individual files',
                ' *',
                ' * @var int',
                ' */',
            )),
            'default' => 5192,
            'type' => 'integer',
        ),
        'boarddir' => array(
            'text' => implode("\n", array(
                '',
                '########## Directories/Files ##########',
                '# Note: These directories do not have to be changed unless you move things.',
                '/**',
                ' * The absolute path to the forum\'s folder. (not just \'.\'!)',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'dirname(__FILE__)',
            'raw_default' => true,
            'type' => 'string',
        ),
        'sourcedir' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Path to the Sources directory.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'dirname(__FILE__) . \'/Sources\'',
            'raw_default' => true,
            'type' => 'string',
        ),
        'packagesdir' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Path to the Packages directory.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => 'dirname(__FILE__) . \'/Packages\'',
            'raw_default' => true,
            'type' => 'string',
        ),
        'tasksdir' => array(
            'text' => implode("\n", array(
                '/**',
                ' * Path to the tasks directory.',
                ' *',
                ' * @var string',
                ' */',
            )),
            'default' => '$sourcedir . \'/tasks\'',
            'raw_default' => true,
            'type' => 'string',
        ),
        array(
            'text' => implode("\n", array(
                '',
                '# Make sure the paths are correct... at least try to fix them.',
                'if (!is_dir(realpath($boarddir)) && file_exists(dirname(__FILE__) . \'/agreement.txt\'))',
                '   $boarddir = dirname(__FILE__);',
                'if (!is_dir(realpath($sourcedir)) && is_dir($boarddir . \'/Sources\'))',
                '   $sourcedir = $boarddir . \'/Sources\';',
                'if (!is_dir(realpath($tasksdir)) && is_dir($sourcedir . \'/tasks\'))',
                '   $tasksdir = $sourcedir . \'/tasks\';',
                'if (!is_dir(realpath($packagesdir)) && is_dir($boarddir . \'/Packages\'))',
                '   $packagesdir = $boarddir . \'/Packages\';',
                'if (!is_dir(realpath($cachedir)) && is_dir($boarddir . \'/cache\'))',
                '   $cachedir = $boarddir . \'/cache\';',
            )),
            'search_pattern' => '~\n?(#[^\n]+)?(?:\n\h*if\s*\((?:\!file_exists\(\$(?>boarddir|sourcedir|tasksdir|packagesdir|cachedir)\)|\!is_dir\(realpath\(\$(?>boarddir|sourcedir|tasksdir|packagesdir|cachedir)\)\))[^;]+\n\h*\$(?>boarddir|sourcedir|tasksdir|packagesdir|cachedir)[^\n]+;)+~sm',
        ),
        'db_character_set' => array(
            'text' => implode("\n", array(
                '',
                '######### Legacy Settings #########',
                '# UTF-8 is now the only character set supported in 2.1.',
            )),
            'default' => 'utf8',
            'type' => 'string',
        ),
        'db_show_debug' => array(
            'text' => implode("\n", array(
                '',
                '######### Developer Settings #########',
                '# Show debug info.',
            )),
            'default' => false,
            'auto_delete' => 2,
            'type' => 'boolean',
        ),
        array(
            'text' => implode("\n", array(
                '',
                '########## Error-Catching ##########',
                '# Note: You shouldn\'t touch these settings.',
                'if (file_exists((isset($cachedir) ? $cachedir : dirname(__FILE__)) . \'/db_last_error.php\'))',
                '   include((isset($cachedir) ? $cachedir : dirname(__FILE__)) . \'/db_last_error.php\');',
                '',
                'if (!isset($db_last_error))',
                '{',
                '   // File does not exist so lets try to create it',
                '   file_put_contents((isset($cachedir) ? $cachedir : dirname(__FILE__)) . \'/db_last_error.php\', \'<\' . \'?\' . "php\n" . \'$db_last_error = 0;\' . "\n" . \'?\' . \'>\');',
                '   $db_last_error = 0;',
                '}',
            )),
            
            'search_pattern' => '~\n?#+ Error.Catching #+.*?\$db_last_error = 0;(?' . '>\s*})?(?=\n|\?' . '>|$)~s',
        ),
        
        'upgradeData' => array(
            'default' => '',
            'auto_delete' => 1,
            'type' => 'string',
        ),
        
        'db_last_error' => array(
            'default' => 0,
            'auto_delete' => 1,
            'type' => 'integer',
        ),
    );
    
    
    if (function_exists('call_integration_hook'))
        call_integration_hook('integrate_update_settings_file', array(&$settings_defs));
    
    if ($settings_vars === array())
    {
        foreach ($settings_defs as $var => $setting_def)
            if (isset($GLOBALS[$var]))
                $settings_vars[$var] = $GLOBALS[$var];
        $new_settings_vars = array_merge($settings_vars, $config_vars);
    }
    
    if (defined('SMF_INSTALLING') && empty($rebuild))
    {
        foreach ($settings_defs as $var => $setting_def)
            if (!in_array($var, array_keys($new_settings_vars)) && !is_int($var))
                unset($settings_defs[$var]);
    }
    
    $type_regex = array(
        'string' =>
            '(?:' .
                
                '(["\'])' .
                
                '(?:.(?!\\1)|\\\(?=\\1))*.?' .
                
                '\\1' .
                
                '(?:\s*\.\s*)*' .
            ')+',
        
        'integer' =>  '["\']?[+-]?\d+["\']?',
        'double' =>  '["\']?[+-]?\d+\.\d+([Ee][+-]\d+)?["\']?',
        
        'boolean' =>  '(?i:TRUE|FALSE|(["\']?)[01]\b\\1)',
        'NULL' =>  '(?i:NULL)',
        
        'array' =>  'array\s*(\((?>[^()]|(?1))*\))',
        'object' =>  '\w+::__set_state\(array\s*(\((?>[^()]|(?1))*\))\)',
    );
    
    $prefix = mt_rand() . '-';
    $neg_index = -1;
    $substitutions = array(
        $neg_index-- => array(
            'search_pattern' => '~^\s*<\?(php\b)?\n?~',
            'placeholder' => '',
            'replace_pattern' => '~^~',
            'replacement' => '<' . "?php\n",
        ),
        $neg_index-- => array(
            'search_pattern' => '~\S\K\s*(\?' . '>)?\s*$~',
            'placeholder' => "\n" . md5($prefix . '?' . '>'),
            'replacement' => "\n\n?" . '>',
        ),
        
        $neg_index-- => array(
            'search_pattern' => '~^if\s*\(file_exists\(dirname\(__FILE__\)\s*\.\s*\'/install\.php\'\)\)\s*(?:({(?>[^{}]|(?1))*})\h*|header(\((?' . '>[^()]|(?2))*\));\n)~m',
            'placeholder' => '',
        ),
    );
    if (defined('SMF_INSTALLING'))
        $substitutions[$neg_index--] = array(
            'search_pattern' => '~/\*.*?SMF\s+1\.\d.*?\*/~s',
            'placeholder' => '',
        );
    foreach ($settings_defs as $var => $setting_def)
    {
        $placeholder = md5($prefix . $var);
        $replacement = '';
        if (!empty($setting_def['text']))
        {
            
            if (strpos($setting_def['text'], "* @package SMF\n") !== false)
            {
                $substitutions[$var]['search_pattern'] = $setting_def['search_pattern'];
                $substitutions[$var]['placeholder'] = '';
                $substitutions[-1]['replacement'] .= $setting_def['text'] . "\n";
            }
            
            elseif (strpos($setting_def['text'], 'Error-Catching') !== false)
            {
                $errcatch_var = $var;
                $substitutions[$var]['search_pattern'] = $setting_def['search_pattern'];
                $substitutions[$var]['placeholder'] = '';
                $substitutions[-2]['replacement'] = "\n" . $setting_def['text'] . $substitutions[-2]['replacement'];
            }
            
            elseif (is_int($var))
            {
                
                if (strpos($setting_def['text'], '# Make sure the paths are correct') !== false)
                    $pathcode_var = $var;
                if (!empty($setting_def['search_pattern']))
                    $substitutions[$var]['search_pattern'] = $setting_def['search_pattern'];
                else
                    $substitutions[$var]['search_pattern'] = '~' . preg_quote($setting_def['text'], '~') . '~';
                $substitutions[$var]['placeholder'] = $placeholder;
                $replacement .= $setting_def['text'] . "\n";
            }
            
            elseif (!empty($rebuild))
                $replacement .= $setting_def['text'] . "\n";
        }
        if (is_string($var))
        {
            
            if (in_array($var, array_keys($new_settings_vars)))
            {
                
                if (is_object($new_settings_vars[$var]) && !method_exists($new_settings_vars[$var], '__set_state'))
                {
                    if (method_exists($new_settings_vars[$var], '__toString'))
                        $new_settings_vars[$var] = (string) $new_settings_vars[$var];
                    else
                        $new_settings_vars[$var] = (array) $new_settings_vars[$var];
                }
                
                if (isset($setting_def['type']))
                {
                    $expected_types = (array) $setting_def['type'];
                    $var_type = gettype($new_settings_vars[$var]);
                    
                    if (!in_array($var_type, $expected_types))
                    {
                        
                        if ($var_type == 'array')
                        {
                            $temp = reset($new_settings_vars[$var]);
                            
                            if (count($new_settings_vars[$var]) === 1 && is_scalar($temp))
                                $new_settings_vars[$var] = $temp;
                            
                            elseif (isset($settings_vars[$var]) && in_array(gettype($settings_vars[$var]), $expected_types))
                                $new_settings_vars[$var] = $settings_vars[$var];
                            
                            else
                                $new_settings_vars[$var] = $setting_def['default'];
                        }
                        
                        
                        foreach (array('boolean', 'integer', 'double', 'string', 'array') as $to_type)
                        {
                            if (in_array($to_type, $expected_types))
                            {
                                settype($new_settings_vars[$var], $to_type);
                                break;
                            }
                        }
                    }
                }
            }
            
            elseif (!empty($setting_def['required']) && !defined('SMF_INSTALLING'))
                return false;
            
            if (!empty($setting_def['search_pattern']))
                $substitutions[$var]['search_pattern'] = $setting_def['search_pattern'];
            else
            {
                $var_pattern = array();
                if (isset($setting_def['type']))
                {
                    foreach ((array) $setting_def['type'] as $type)
                        $var_pattern[] = $type_regex[$type];
                }
                if (in_array($var, array_keys($config_vars)))
                {
                    $var_pattern[] = @$type_regex[gettype($config_vars[$var])];
                    if (is_string($config_vars[$var]) && strpos($config_vars[$var], dirname($settingsFile)) === 0)
                        $var_pattern[] = '(?:__DIR__|dirname\(__FILE__\)) . \'' . (preg_quote(str_replace(dirname($settingsFile), '', $config_vars[$var]), '~')) . '\'';
                }
                if (in_array($var, array_keys($settings_vars)))
                {
                    $var_pattern[] = @$type_regex[gettype($settings_vars[$var])];
                    if (is_string($settings_vars[$var]) && strpos($settings_vars[$var], dirname($settingsFile)) === 0)
                        $var_pattern[] = '(?:__DIR__|dirname\(__FILE__\)) . \'' . (preg_quote(str_replace(dirname($settingsFile), '', $settings_vars[$var]), '~')) . '\'';
                }
                if (!empty($setting_def['raw_default']) && $setting_def['default'] !== '')
                {
                    $var_pattern[] = preg_replace('/\s+/', '\s+', preg_quote($setting_def['default'], '~'));
                    if (strpos($setting_def['default'], 'dirname(__FILE__)') !== false)
                        $var_pattern[] = preg_replace('/\s+/', '\s+', preg_quote(str_replace('dirname(__FILE__)', '__DIR__', $setting_def['default']), '~'));
                    if (strpos($setting_def['default'], '__DIR__') !== false)
                        $var_pattern[] = preg_replace('/\s+/', '\s+', preg_quote(str_replace('__DIR__', 'dirname(__FILE__)', $setting_def['default']), '~'));
                }
                $var_pattern = array_unique($var_pattern);
                $var_pattern = count($var_pattern) > 1 ? '(?:' . (implode('|', $var_pattern)) . ')' : $var_pattern[0];
                $substitutions[$var]['search_pattern'] = '~(?<=^|\s)\h*\$' . preg_quote($var, '~') . '\s*=\s*' . $var_pattern . ';~' . (!empty($context['utf8']) ? 'u' : '');
            }
            
            if (!empty($setting_def['replace_pattern']))
                $substitutions[$var]['replace_pattern'] = $setting_def['replace_pattern'];
            else
                $substitutions[$var]['placeholder'] = $placeholder;
            
            
            if (!empty($setting_def['auto_delete']) && empty($new_settings_vars[$var]))
            {
                if ($setting_def['auto_delete'] === 2 && empty($rebuild) && in_array($var, array_keys($new_settings_vars)))
                {
                    $replacement .= '$' . $var . ' = ' . ($new_settings_vars[$var] === $setting_def['default'] && !empty($setting_def['raw_default']) ? sprintf($new_settings_vars[$var]) : smf_var_export($new_settings_vars[$var], true)) . ";";
                }
                else
                {
                    $replacement = '';
                    
                    $substitutions[$var]['search_pattern'] = str_replace('(?<=^|\s)', '\n?', $substitutions[$var]['search_pattern']);
                }
            }
            
            elseif (in_array($var, array_keys($new_settings_vars)))
            {
                $replacement .= '$' . $var . ' = ' . ($new_settings_vars[$var] === $setting_def['default'] && !empty($setting_def['raw_default']) ? sprintf($new_settings_vars[$var]) : smf_var_export($new_settings_vars[$var], true)) . ";";
            }
            
            elseif (isset($setting_def['default']))
            {
                $replacement .= '$' . $var . ' = ' . (!empty($setting_def['raw_default']) ? sprintf($setting_def['default']) : smf_var_export($setting_def['default'], true)) . ';';
            }
            
            else
                $replacement .= '$' . $var . ' = null;';
        }
        $substitutions[$var]['replacement'] = $replacement;
        
        unset($new_settings_vars[$var]);
    }
    
    foreach ($new_settings_vars as $var => $val)
    {
        $var_pattern = array();
        if (in_array($var, array_keys($config_vars)))
            $var_pattern[] = $type_regex[gettype($config_vars[$var])];
        if (in_array($var, array_keys($settings_vars)))
            $var_pattern[] = $type_regex[gettype($settings_vars[$var])];
        $var_pattern = array_unique($var_pattern);
        $var_pattern = count($var_pattern) > 1 ? '(?:' . (implode('|', $var_pattern)) . ')' : $var_pattern[0];
        $placeholder = md5($prefix . $var);
        $substitutions[$var]['search_pattern'] = '~(?<=^|\s)\h*\$' . preg_quote($var, '~') . '\s*=\s*' . $var_pattern . ';~' . (!empty($context['utf8']) ? 'u' : '');
        $substitutions[$var]['placeholder'] = $placeholder;
        $substitutions[$var]['replacement'] = '$' . $var . ' = ' . smf_var_export($val, true) . ";";
    }
    
    if (defined('SMF_INSTALLING') && empty($rebuild))
    {
        preg_match_all('~^\h*\$(\w+)\s*=\s*~m', $substitutions[$pathcode_var]['replacement'], $matches);
        $missing_pathvars = array_diff($matches[1], array_keys($substitutions));
        if (!empty($missing_pathvars))
        {
            foreach ($missing_pathvars as $var)
            {
                $substitutions[$pathcode_var]['replacement'] = preg_replace('~\nif[^\n]+\$' . $var . '[^\n]+\n\h*\$' . $var . ' = [^\n]+~', '', $substitutions[$pathcode_var]['replacement']);
            }
        }
    }
    
    uksort($substitutions, function($a, $b) {
        if (is_int($a) && is_int($b))
            return $a > $b;
        elseif (is_int($a))
            return -1;
        elseif (is_int($b))
            return 1;
        else
            return strcasecmp($b, $a);
    });
    
    
    
    $settingsText = trim(strtr(file_get_contents($settingsFile), array("\r\n" => "\n", "\r" => "\n")));
    
    if ($settingsText == '' || substr($settingsText, 0, 5) !== '<' . '?php')
    {
        
        if (file_exists(dirname($settingsFile) . '/Settings_bak.php'))
            $settingsText = strtr(file_get_contents(dirname($settingsFile) . '/Settings_bak.php'), array("\r\n" => "\n", "\r" => "\n"));
        
        if ($settingsText == '' || substr($settingsText, 0, 5) !== '<' . '?php' || substr($settingsText, -2) !== '?' . '>')
        {
            $settingsText = '<' . "?php\n";
            foreach ($settings_defs as $var => $setting_def)
            {
                if (!empty($setting_def['text']) && strpos($substitutions[$var]['replacement'], $setting_def['text']) === false)
                    $substitutions[$var]['replacement'] = $setting_def['text'] . "\n" . $substitutions[$var]['replacement'];
                $settingsText .= $substitutions[$var]['replacement'] . "\n";
            }
            $settingsText .= "\n\n?" . '>';
            $rebuild = true;
        }
    }
    
    if (preg_match_all('/<<<(\'?)(\w+)\'?\n(.*?)\n\2;$/m', $settingsText, $matches))
    {
        foreach ($matches[0] as $mkey => $heredoc)
        {
            if (!empty($matches[1][$mkey]))
                $heredoc_replacements[$heredoc] = var_export($matches[3][$mkey], true) . ';';
            else
                $heredoc_replacements[$heredoc] = '"' . strtr(substr(var_export($matches[3][$mkey], true), 1, -1), array("\\'" => "'", '"' => '\"')) . '";';
        }
        $settingsText = strtr($settingsText, $heredoc_replacements);
    }
    
    $last_var = null;
    $bare_settingsText = $settingsText;
    $force_before_pathcode = array();
    foreach ($substitutions as $var => $substitution)
    {
        $placeholders[$var] = $substitution['placeholder'];
        if (!empty($substitution['placeholder']))
        {
            $simple_replacements[$substitution['placeholder']] = $substitution['replacement'];
        }
        elseif (!empty($substitution['replace_pattern']))
        {
            $replace_patterns[$var] = $substitution['replace_pattern'];
            $replace_strings[$var] = $substitution['replacement'];
        }
        if (strpos($substitutions[$pathcode_var]['replacement'], '$' . $var . ' = ') !== false)
            $force_before_pathcode[] = $var;
        
        preg_match_all($substitution['search_pattern'], $bare_settingsText, $matches);
        if ((is_string($var) || $var === $pathcode_var) && count($matches[0]) !== 1 && $substitution['replacement'] !== '')
        {
            
            if (count($matches[0]) > 1)
            {
                if (is_string($var))
                {
                    
                    $sp = substr($substitution['search_pattern'], 1);
                    if (strpos($sp, '(?<=^|\s)') === 0)
                        $sp = substr($sp, 9);
                    if (strpos($sp, '^') === 0 || strpos($sp, '(?<') === 0)
                        return false;
                    
                    
                    $sp = '~(?:^|//[^\n]+c\n|\*/|[;}]|' . implode('|', array_filter($placeholders)) . ')\s*' . (strpos($sp, '\K') === false ? '\K' : '') . $sp;
                    preg_match_all($sp, $settingsText, $matches);
                }
                else
                    $sp = $substitution['search_pattern'];
                
                if (count($matches[0]) > 0)
                {
                    
                    if (count($matches[0]) > 1)
                        $settingsText = preg_replace($sp, '', $settingsText, count($matches[0]) - 1);
                    
                    $settingsText = preg_replace($sp, $substitution['placeholder'], $settingsText, 1);
                }
                
                else
                {
                    
                    unset($substitutions[$var], $new_settings_vars[$var], $settings_defs[$var], $simple_replacements[$substitution['placeholder']], $replace_patterns[$var], $replace_strings[$var]);
                    continue;
                }
            }
            
            elseif (count($matches[0]) === 0)
            {
                $found = false;
                $in_c = in_array($var, array_keys($config_vars));
                $in_s = in_array($var, array_keys($settings_vars));
                
                if (!preg_match('~(^|\s)\$' . preg_quote($var, '~') . '\s*=\s*~', $bare_settingsText))
                {
                    
                    
                    if ($in_s)
                        unset($substitutions[$var], $settings_defs[$var]);
                    
                    
                    elseif ($in_c)
                        $new_settings_vars[$var] = $config_vars[$var];
                    continue;
                }
                
                foreach (array('scalar', 'object', 'array') as $type)
                {
                    
                    if ($type == 'scalar')
                        $sp = '(?:' . (implode('|', array_diff_key($type_regex, array($in_c ? gettype($config_vars[$var]) : ($in_s ? gettype($settings_vars[$var]) : PHP_INT_MAX) => '', 'array' => '', 'object' => '')))) . ')';
                    
                    elseif ($type == 'object')
                    {
                        if (strpos($settingsText, '__set_state') === false)
                            continue;
                        $sp = $type_regex['object'];
                    }
                    
                    else
                        $sp = $type_regex['array'];
                    if (preg_match('~(^|\s)\$' . preg_quote($var, '~') . '\s*=\s*' . $sp . '~', $bare_settingsText, $derp))
                    {
                        $settingsText = preg_replace('~(^|\s)\$' . preg_quote($var, '~') . '\s*=\s*' . $sp . '~', $substitution['placeholder'], $settingsText);
                        $found = true;
                        break;
                    }
                }
                
                if (!$found)
                {
                    
                    unset($substitutions[$var], $new_settings_vars[$var], $settings_defs[$var], $simple_replacements[$substitution['placeholder']], $replace_patterns[$var], $replace_strings[$var]);
                    continue;
                }
            }
        }
        
        else
            $settingsText = preg_replace($substitution['search_pattern'], $substitution['placeholder'], $settingsText);
        
        if (is_int($last_var) && is_string($var))
            $bare_settingsText = strip_php_comments($settingsText);
        $last_var = $var;
    }
    
    if (!empty($rebuild))
    {
        
        $settingsText = str_replace(array($substitutions[-1]['placeholder'], $substitutions[-2]['placeholder']), '', $settingsText);
        
        foreach ($settings_defs as $var => $setting_def)
        {
            if (isset($setting_def['text']))
                $settingsText = strtr($settingsText, array($setting_def['text'] . "\n" => '', $setting_def['text'] => '',));
        }
        
        $bare_settingsText = strip_php_comments($settingsText);
        
        foreach ($placeholders as $placeholder)
        {
            $bare_settingsText = str_replace(array($placeholder . "\n\n", $placeholder), $placeholder . "\n", $bare_settingsText);
        }
        $bare_settingsText = preg_replace('/\h+$/m', '', rtrim($bare_settingsText));
        
        $sections = array(array());
        $section_num = 0;
        $trimmed_placeholders = array_filter(array_map('trim', $placeholders));
        $newsection_placeholders = array();
        $all_custom_content = '';
        foreach ($substitutions as $var => $substitution)
        {
            if (is_int($var) && ($var === -2 || $var > 0) && isset($trimmed_placeholders[$var]) && strpos($bare_settingsText, $trimmed_placeholders[$var]) !== false)
                $newsection_placeholders[$var] = $trimmed_placeholders[$var];
        }
        foreach (preg_split('~(?<=' . implode('|', $trimmed_placeholders) . ')|(?=' . implode('|', $trimmed_placeholders) . ')~', $bare_settingsText) as $part)
        {
            $part = trim($part);
            if (empty($part))
                continue;
            
            if (in_array($part, $trimmed_placeholders) && !in_array($part, $newsection_placeholders))
            {
                $sections[$section_num][] = $part;
            }
            
            else
            {
                if (!empty($sections[$section_num]))
                    ++$section_num;
                $sections[$section_num][] = $part;
                ++$section_num;
                if (!in_array($part, $trimmed_placeholders))
                    $all_custom_content .= "\n" . $part;
            }
        }
        
        $new_settingsText = '';
        $done_defs = array();
        $sectionkeys = array_keys($sections);
        foreach ($sections as $sectionkey => $section)
        {
            
            if (count($section) === 1 && !in_array($section[0], $trimmed_placeholders))
            {
                $prev_section_end = $sectionkey < 1 ? 0 : strpos($settingsText, end($sections[$sectionkey - 1])) + strlen(end($sections[$sectionkey - 1]));
                $next_section_start = $sectionkey == end($sectionkeys) ? strlen($settingsText) : strpos($settingsText, $sections[$sectionkey + 1][0]);
                $new_settingsText .= "\n" . substr($settingsText, $prev_section_end, $next_section_start - $prev_section_end) . "\n";
            }
            
            else
            {
                $section_parts = array_flip($section);
                $pathcode_reached = false;
                foreach ($settings_defs as $var => $setting_def)
                {
                    if ($var === $pathcode_var)
                        $pathcode_reached = true;
                    
                    if (in_array($var, $done_defs))
                        continue;
                    
                    if (isset($newsection_placeholders[$var]) && count($section) !== 1)
                        break;
                    
                    
                    if (empty($section_parts) && $sectionkey < (count($sections) - 1))
                        break;
                    $p = trim($substitutions[$var]['placeholder']);
                    
                    if ($p === '')
                        continue;
                    
                    if (strpos($new_settingsText, trim($substitutions[$pathcode_var]['placeholder'])) !== false && in_array($var, $force_before_pathcode))
                    {
                        $new_settingsText = strtr($new_settingsText, array($substitutions[$pathcode_var]['placeholder'] => $p . "\n" . $substitutions[$pathcode_var]['placeholder']));
                        $bare_settingsText .= "\n" . $substitutions[$var]['placeholder'];
                        $done_defs[] = $var;
                        unset($section_parts[trim($substitutions[$var]['placeholder'])]);
                    }
                    
                    elseif (in_array($p, $section))
                    {
                        $new_settingsText .= "\n" . $substitutions[$var]['placeholder'];
                        $done_defs[] = $var;
                        unset($section_parts[trim($substitutions[$var]['placeholder'])]);
                    }
                    
                    elseif (is_string($var) && strpos($new_settingsText, $p) === false && strpos($all_custom_content, '$' . $var) === false)
                    {
                        $new_settingsText .= "\n" . $substitutions[$var]['placeholder'];
                        $done_defs[] = $var;
                        unset($section_parts[trim($substitutions[$var]['placeholder'])]);
                    }
                    
                    elseif (strpos($bare_settingsText, $p) === false)
                    {
                        
                        
                        if (!isset($newsection_placeholders[$pathcode_var]) && $pathcode_reached === true && $sectionkey < (count($sections) - 1))
                            break;
                        $new_settingsText .= "\n" . $substitutions[$var]['placeholder'];
                        $bare_settingsText .= "\n" . $substitutions[$var]['placeholder'];
                        $done_defs[] = $var;
                        unset($section_parts[trim($substitutions[$var]['placeholder'])]);
                    }
                }
            }
        }
        $settingsText = $new_settingsText;
        
        foreach (array(-1, -2) as $var)
        {
            if (!empty($substitutions[$var]['placeholder']) && strpos($settingsText, $substitutions[$var]['placeholder']) === false);
            {
                $settingsText = ($var == -1 ? $substitutions[$var]['placeholder'] : '') . $settingsText . ($var == -2 ? $substitutions[$var]['placeholder'] : '');
            }
        }
    }
    
    else
    {
        $pathcode_pos = strpos($settingsText, $substitutions[$pathcode_var]['placeholder']);
        if ($pathcode_pos !== false)
        {
            foreach ($force_before_pathcode as $var)
            {
                if (!empty($substitutions[$var]['placeholder']) && strpos($settingsText, $substitutions[$var]['placeholder']) > $pathcode_pos)
                {
                    $settingsText = strtr($settingsText, array(
                        $substitutions[$var]['placeholder'] => '',
                        $substitutions[$pathcode_var]['placeholder'] => $substitutions[$var]['placeholder'] . "\n" . $substitutions[$pathcode_var]['placeholder'],
                    ));
                }
            }
        }
    }
    
    
    $settingsText = strtr($settingsText, $simple_replacements);
    
    if (!empty($replace_patterns))
        $settingsText = preg_replace($replace_patterns, $replace_strings, $settingsText);
    
    if (strpos($settingsText, $substitutions[$pathcode_var]['replacement']) === false)
        $settingsText = preg_replace('~(?=\n#+ Error.Catching #+)~', "\n" . $substitutions[$pathcode_var]['replacement'] . "\n", $settingsText);
    
    if (empty($rebuild))
    {
        
        $bare_settingsText = $settingsText;
        foreach ($substitutions as $var => $substitution)
        {
            if (!is_int($var))
                break;
            if (isset($substitution['replacement']))
                $bare_settingsText = str_replace($substitution['replacement'], '', $bare_settingsText);
        }
        $bare_settingsText = strip_php_comments($bare_settingsText);
        
        $pathcode_reached = false;
        foreach ($settings_defs as $var => $setting_def)
        {
            if ($var === $pathcode_var)
                $pathcode_reached = true;
            if (is_int($var))
                continue;
            
            if (preg_match($substitutions[$var]['search_pattern'], $bare_settingsText))
                continue;
            
            if (!$pathcode_reached || in_array($var, $force_before_pathcode))
            {
                $settingsText = preg_replace($substitutions[$pathcode_var]['search_pattern'], $substitutions[$var]['replacement'] . "\n$0", $settingsText);
            }
            else
            {
                $settingsText = preg_replace($substitutions[$pathcode_var]['search_pattern'], "$0\n" . $substitutions[$var]['replacement'], $settingsText);
            }
        }
    }
    
    foreach ($new_settings_vars as $var => $val)
    {
        if (isset($substitutions[$var]) && !preg_match($substitutions[$var]['search_pattern'], $settingsText))
        {
            if (!isset($settings_defs[$var]) && strpos($settingsText, '# Custom Settings #') === false)
                $settingsText = preg_replace('~(?=\n#+ Error.Catching #+)~', "\n\n######### Custom Settings #########\n", $settingsText);
            $settingsText = preg_replace('~(?=\n#+ Error.Catching #+)~', $substitutions[$var]['replacement'] . "\n", $settingsText);
        }
    }
    
    $settingsText = preg_replace('~\n\s*\n~', "\n\n", $settingsText);
    
    $temp_sfile = tempnam(sys_get_temp_dir(), md5($prefix . 'Settings.php'));
    file_put_contents($temp_sfile, $settingsText);
    $result = get_current_settings(filemtime($temp_sfile), $temp_sfile);
    unlink($temp_sfile);
    
    if ($result === false)
        return empty($rebuild) ? updateSettingsFile($config_vars, $keep_quotes, true) : false;
    
    $success = safe_file_write($settingsFile, $settingsText, dirname($settingsFile) . '/Settings_bak.php', $last_settings_change);
    
    $mtime = filemtime($settingsFile);
    return $success;
}
function get_current_settings($mtime = null, $settingsFile = null)
{
    $mtime = is_null($mtime) ? (defined('TIME_START') ? TIME_START : $_SERVER['REQUEST_TIME']) : (int) $mtime;
    if (!is_file($settingsFile))
    {
        foreach (get_included_files() as $settingsFile)
            if (basename($settingsFile) === 'Settings.php')
                break;
        if (basename($settingsFile) !== 'Settings.php')
            return false;
    }
    
    clearstatcache();
    if (filemtime($settingsFile) > $mtime)
        return false;
    
    $settingsText = trim(file_get_contents($settingsFile));
    if (substr($settingsText, 0, 5) == '<' . '?php')
        $settingsText = substr($settingsText, 5);
    if (substr($settingsText, -2) == '?' . '>')
        $settingsText = substr($settingsText, 0, -2);
    
    $settingsText = strtr($settingsText, array(
        '__FILE__' => var_export($settingsFile, true),
        '__DIR__' => var_export(dirname($settingsFile), true),
    ));
    
    $settingsText = preg_replace_callback(
        '~\bdefine\s*\(\s*(["\'])(\w+)\1~',
        function ($matches)
        {
            return 'define(\'' . md5(mt_rand()) . '\'';
        },
        $settingsText
    );
    
    try
    {
        if($settingsText !== '' && @eval($settingsText) === false)
            throw new ErrorException('eval error');
        unset($mtime, $settingsFile, $settingsText);
        $defined_vars = get_defined_vars();
    }
    catch (Throwable $e) {}
    catch (ErrorException $e) {}
    if (isset($e))
        return false;
    return $defined_vars;
}
function safe_file_write($file, $data, $backup_file = null, $mtime = null, $append = false)
{
    global $cachedir;
    
    if (!file_exists($file) && !is_dir(dirname($file)))
        return false;
    if (!is_int($mtime))
        $mtime = $_SERVER['REQUEST_TIME'];
    $temp_dir = is_dir(@realpath($cachedir)) ? $cachedir : sys_get_temp_dir();
    
    $temp_sfile = tempnam($temp_dir, pathinfo($file, PATHINFO_FILENAME) . '.');
    if (!empty($backup_file))
        $temp_bfile = tempnam($temp_dir, pathinfo($backup_file, PATHINFO_FILENAME) . '.');
    
    $failed = false;
    foreach (array($file, $backup_file) as $sf)
    {
        if (empty($sf))
            continue;
        if (!file_exists($sf))
            touch($sf);
        elseif (!is_file($sf))
            $failed = true;
        if (!$failed)
            $failed = !smf_chmod($sf);
    }
    
    if (!$failed && disk_free_space(dirname($file)) < (strlen($data) + filesize($file) + (!empty($backup_file) ? filesize($backup_file) : 0)))
        $failed = true;
    
    if (!$failed && file_put_contents($temp_sfile, $data, LOCK_EX) !== strlen($data))
        $failed = true;
    
    if (!$failed)
    {
        
        if (file_exists($backup_file))
            $temp_bfile_saved = @copy($backup_file, $temp_bfile);
        
        clearstatcache();
        if (filemtime($file) <= $mtime)
        {
            
            $sfhandle = @fopen($file, 'c');
            
            if ($sfhandle !== false)
            {
                
                flock($sfhandle, LOCK_EX);
                
                $temp_sfile_saved = @copy($file, $temp_sfile);
                
                if ($temp_sfile_saved)
                {
                    if (empty($append))
                    {
                        ftruncate($sfhandle, 0);
                        rewind($sfhandle);
                    }
                    $failed = fwrite($sfhandle, $data) !== strlen($data);
                }
                else
                    $failed = true;
                
                if ($failed)
                {
                    if (!empty($temp_sfile_saved))
                        @rename($temp_sfile, $file);
                    if (!empty($temp_bfile_saved))
                        @rename($temp_bfile, $backup_file);
                }
                
                elseif (!empty($backup_file))
                    @rename($temp_sfile, $backup_file);
                
                flock($sfhandle, LOCK_UN);
                fclose($sfhandle);
            }
        }
    }
    
    @unlink($temp_sfile);
    @unlink($temp_bfile);
    if ($failed)
        return false;
    
    
    if (function_exists('opcache_invalidate'))
        opcache_invalidate($file, true);
    return true;
}
function smf_var_export($var)
{
    
    if (is_array($var))
    {
        $return = array();
        foreach ($var as $key => $value)
            $return[] = var_export($key, true) . ' => ' . smf_var_export($value);
        return 'array(' . implode(', ', $return) . ')';
    }
    
    elseif (is_string($var) && (strpos($var, "\n") !== false || strpos($var, "\r") !== false))
    {
        return strtr(preg_replace_callback('/[\r\n]+/', function($m) {
            return '\' . "' . strtr($m[0], array("\r" => '\r', "\n" => '\n')) . '" . \'';
        }, $var), array("'' . " => '', " . ''" => ''));
    }
    
    elseif (in_array(gettype($var), array('boolean', 'NULL')))
        return strtolower(var_export($var, true));
    
    else
        return var_export($var, true);
};
function strip_php_comments($code_str, $line_ending = null)
{
    
    
    if (!in_array($line_ending, array("\r", "\n", "\r\n")))
    {
        if (strpos($code_str, "\r\n") !== false)
            $line_ending = "\r\n";
        elseif (strpos($code_str, "\n") !== false)
            $line_ending = "\n";
        elseif (strpos($code_str, "\r") !== false)
            $line_ending = "\r";
    }
    
    if (preg_match_all('/<<<(\'?)(\w+)\'?'. $line_ending . '(.*?)'. $line_ending . '\2;$/m', $code_str, $matches))
    {
        foreach ($matches[0] as $mkey => $heredoc)
        {
            if (!empty($matches[1][$mkey]))
                $heredoc_replacements[$heredoc] = var_export($matches[3][$mkey], true) . ';';
            else
                $heredoc_replacements[$heredoc] = '"' . strtr(substr(var_export($matches[3][$mkey], true), 1, -1), array("\\'" => "'", '"' => '\"')) . '";';
        }
        $code_str = strtr($code_str, $heredoc_replacements);
    }
    
    $parts = preg_split('~(?=#+|/(?=/|\*)|\*/|'. $line_ending . '|(?<!\\\)[\'"])~m', $code_str);
    $in_string = 0;
    $in_comment = 0;
    foreach ($parts as $partkey => $part)
    {
        $one_char = substr($part, 0, 1);
        $two_char = substr($part, 0, 2);
        $to_remove = 0;
        
        if ($one_char == "'")
        {
            if (!empty($in_comment))
                $in_string = 0;
            elseif (in_array($in_string, array(0, 1)))
                $in_string = ($in_string ^ 1);
        }
        elseif ($one_char == '"')
        {
            if (!empty($in_comment))
                $in_string = 0;
            elseif (in_array($in_string, array(0, 2)))
                $in_string = ($in_string ^ 2);
        }
        
        elseif ($one_char == '#' || $two_char == '//')
        {
            $in_comment = !empty($in_string) ? 0 : (empty($in_comment) ? 1 : $in_comment);
        }
        elseif (($line_ending === "\r\n" && $two_char === $line_ending) || $one_char == $line_ending)
        {
            if ($in_comment == 1)
            {
                $in_comment = 0;
                
                if ($parts[$partkey - 1] === $line_ending)
                    $to_remove = strlen($line_ending);
            }
        }
        elseif ($two_char == '/*')
        {
            $in_comment = !empty($in_string) ? 0 : (empty($in_comment) ? 2 : $in_comment);
        }
        elseif ($two_char == '*/')
        {
            if ($in_comment == 2)
            {
                $in_comment = 0;
                
                $to_remove = 2;
            }
        }
        if (empty($in_comment))
            $parts[$partkey] = strlen($part) > $to_remove ? substr($part, $to_remove) : '';
        else
            $parts[$partkey] = '';
    }
    return implode('', $parts);
}
function updateDbLastError($time)
{
    global $boarddir, $cachedir;
    
    if (!empty($cachedir) && is_writable($cachedir))
        $errorfile = $cachedir . '/db_last_error.php';
    elseif (file_exists(dirname(__DIR__) . '/cache'))
        $errorfile = dirname(__DIR__) . '/cache/db_last_error.php';
    else
        $errorfile = dirname(__DIR__) . '/db_last_error.php';
    file_put_contents($errorfile, '<' . '?' . "php\n" . '$db_last_error = ' . $time . ';' . "\n" . '?' . '>', LOCK_EX);
    @touch($boarddir . '/' . 'Settings.php');
}
function updateAdminPreferences()
{
    global $options, $context, $smcFunc, $settings, $user_info;
    
    if (!isset($context['admin_preferences']))
        return false;
    
    $options['admin_preferences'] = $smcFunc['json_encode']($context['admin_preferences']);
    
    $smcFunc['db_query']('', '
        DELETE FROM {db_prefix}themes
        WHERE id_theme != {int:default_theme}
            AND variable = {string:admin_preferences}',
        array(
            'default_theme' => 1,
            'admin_preferences' => 'admin_preferences',
        )
    );
    
    $smcFunc['db_insert']('replace',
        '{db_prefix}themes',
        array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'),
        array($user_info['id'], 1, 'admin_preferences', $options['admin_preferences']),
        array('id_member', 'id_theme', 'variable')
    );
    
    cache_put_data('theme_settings-' . $settings['theme_id'] . ':' . $user_info['id'], null, 0);
}
function emailAdmins($template, $replacements = array(), $additional_recipients = array())
{
    global $smcFunc, $sourcedir, $language, $modSettings;
    
    require_once($sourcedir . '/Subs-Post.php');
    
    require_once($sourcedir . '/Subs-Members.php');
    $members = membersAllowedTo('admin_forum');
    
    require_once($sourcedir . '/Subs-Notify.php');
    $prefs = getNotifyPrefs($members, 'announcements', true);
    $request = $smcFunc['db_query']('', '
        SELECT id_member, member_name, real_name, lngfile, email_address
        FROM {db_prefix}members
        WHERE id_member IN({array_int:members})',
        array(
            'members' => $members,
        )
    );
    $emails_sent = array();
    while ($row = $smcFunc['db_fetch_assoc']($request))
    {
        if (empty($prefs[$row['id_member']]['announcements']))
            continue;
        
        $replacements['IDMEMBER'] = $row['id_member'];
        $replacements['REALNAME'] = $row['member_name'];
        $replacements['USERNAME'] = $row['real_name'];
        
        $emaildata = loadEmailTemplate($template, $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
        
        sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, $template, $emaildata['is_html'], 1);
        
        $emails_sent[] = $row['email_address'];
    }
    $smcFunc['db_free_result']($request);
    
    if (!empty($additional_recipients))
        foreach ($additional_recipients as $recipient)
        {
            if (in_array($recipient['email'], $emails_sent))
                continue;
            $replacements['IDMEMBER'] = $recipient['id'];
            $replacements['REALNAME'] = $recipient['name'];
            $replacements['USERNAME'] = $recipient['name'];
            
            $emaildata = loadEmailTemplate($template, $replacements, empty($recipient['lang']) || empty($modSettings['userLanguage']) ? $language : $recipient['lang']);
            
            sendmail($recipient['email'], $emaildata['subject'], $emaildata['body'], null, $template, $emaildata['is_html'], 1);
        }
}
?>