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: 2169: 2170: 2171: 2172: 2173: 2174: 2175: 2176: 2177: 2178: 2179: 2180: 2181: 2182: 2183: 2184: 2185: 2186: 2187: 2188: 2189: 2190: 2191: 2192: 2193: 2194: 2195: 2196: 2197: 2198: 2199: 2200: 2201: 2202: 2203: 2204: 2205: 2206: 2207: 2208: 2209: 2210: 2211: 2212: 2213: 2214: 2215: 2216: 2217: 2218: 2219: 2220: 2221: 2222: 2223: 2224: 2225: 2226: 2227: 2228: 2229: 2230: 2231: 2232: 2233: 2234: 2235: 2236: 2237: 2238: 2239: 2240: 2241: 2242: 2243: 2244: 2245: 2246: 2247: 2248: 2249: 2250: 2251: 2252: 2253: 2254: 2255: 2256: 2257: 2258: 2259: 2260: 2261: 2262: 2263: 2264: 2265: 2266: 2267: 2268: 2269: 2270: 2271: 2272: 2273: 2274: 2275: 2276: 2277: 2278: 2279: 2280: 2281: 2282: 2283: 2284: 2285: 2286: 2287: 2288: 2289: 2290: 2291: 2292: 2293: 2294: 2295: 2296: 2297: 2298: 2299: 2300: 2301: 2302: 2303: 2304: 2305: 2306: 2307: 2308: 2309: 2310: 2311: 2312: 2313: 2314: 2315: 2316: 2317: 2318: 2319: 2320: 2321: 2322: 2323: 2324: 2325: 2326: 2327: 2328: 2329: 2330: 2331: 2332: 2333: 2334: 2335: 2336: 2337: 2338: 2339: 2340: 2341: 2342: 2343: 2344: 2345: 2346: 2347: 2348: 2349: 2350: 2351: 2352: 2353: 2354: 2355: 2356: 2357: 2358: 2359: 2360: 2361: 2362: 2363: 2364: 2365: 2366: 2367: 2368: 2369: 2370: 2371: 2372: 2373: 2374: 2375: 2376: 2377: 2378: 2379: 2380: 2381: 2382: 2383: 2384: 2385: 2386: 2387: 2388: 2389: 2390: 2391: 2392: 2393: 2394: 2395: 2396: 2397: 2398: 2399: 2400: 2401: 2402: 2403: 2404: 2405: 2406: 2407: 2408: 2409: 2410: 2411: 2412: 2413: 2414: 2415: 2416: 2417: 2418: 2419: 2420: 2421: 2422: 2423: 2424: 2425: 2426: 2427: 2428: 2429: 2430: 2431: 2432: 2433: 2434: 2435: 2436: 2437: 2438: 2439: 2440: 2441: 2442: 2443: 2444: 2445: 2446: 2447: 2448: 2449: 2450: 2451: 2452: 2453: 2454: 2455: 2456: 2457: 2458: 2459: 2460: 2461: 2462: 2463: 2464: 2465: 2466: 2467: 2468: 2469: 2470: 2471: 2472: 2473: 2474: 2475: 2476: 2477: 2478: 2479: 2480: 2481: 2482: 2483: 2484: 2485: 2486: 2487: 2488: 2489: 2490: 2491: 2492: 2493: 2494: 2495: 2496: 2497: 2498: 2499: 2500: 2501: 2502: 2503: 2504: 2505: 2506: 2507: 2508: 2509: 2510: 2511: 2512: 2513: 2514: 2515: 2516: 2517: 2518: 2519: 2520: 2521: 2522: 2523: 2524: 2525: 2526: 2527: 2528: 2529: 2530: 2531: 2532: 2533: 2534: 2535: 2536: 2537: 2538: 2539: 2540: 2541: 2542: 2543: 2544: 2545: 2546: 2547: 2548: 2549: 2550: 2551: 2552: 2553: 2554: 2555: 2556: 2557: 2558: 2559: 2560: 2561: 2562: 2563: 2564: 2565: 2566: 2567: 2568: 2569: 2570: 2571: 2572: 2573: 2574: 2575: 2576: 2577: 2578: 2579: 2580: 2581: 2582: 2583: 2584: 2585: 2586: 2587: 2588: 2589: 2590: 2591: 2592: 2593: 2594: 2595: 2596: 2597: 2598: 2599: 2600: 2601: 2602: 2603: 2604: 2605: 2606: 2607: 2608: 2609: 2610: 2611: 2612: 2613: 2614: 2615: 2616: 2617: 2618: 2619: 2620: 2621: 2622: 2623: 2624: 2625: 2626: 2627: 2628: 2629: 2630: 2631: 2632: 2633: 2634: 2635: 2636: 2637: 2638: 2639: 2640: 2641: 2642: 2643: 2644: 2645: 2646: 2647: 2648: 2649: 2650: 2651: 2652: 2653: 2654: 2655: 2656: 2657: 2658: 2659: 2660: 2661: 2662: 2663: 2664: 2665: 2666: 2667: 2668: 2669: 2670: 2671: 2672: 2673: 2674: 2675: 2676: 2677: 2678: 2679: 2680: 2681: 2682: 2683: 2684: 2685: 2686: 2687: 2688: 2689: 2690: 2691: 2692: 2693: 2694: 2695: 2696: 2697: 2698: 2699: 2700: 2701: 2702: 2703: 2704: 2705: 2706: 2707: 2708: 2709: 2710: 2711: 2712: 2713: 2714: 2715: 2716: 2717: 2718: 2719: 2720: 2721: 2722: 2723: 2724: 2725: 2726: 2727: 2728: 2729: 2730: 2731: 2732: 2733: 2734: 2735: 2736: 2737: 2738: 2739: 2740: 2741: 2742: 2743: 2744: 2745: 2746: 2747: 2748: 2749: 2750: 2751: 2752: 2753: 2754: 2755: 2756: 2757: 2758: 2759: 2760: 2761: 2762: 2763: 2764: 2765: 2766: 2767: 2768: 2769: 2770: 2771: 2772: 2773: 2774: 2775: 2776: 2777: 2778: 2779: 2780: 2781: 2782: 2783: 2784: 2785: 2786: 2787: 2788: 2789: 2790: 2791: 2792: 2793: 2794: 2795: 2796: 2797: 2798: 2799: 2800: 2801: 2802: 2803: 2804: 2805: 2806: 2807: 2808: 2809: 2810: 2811: 2812: 2813: 2814: 2815: 2816: 2817: 2818: 2819: 2820: 2821: 2822: 2823: 2824: 2825: 2826: 2827: 2828: 2829: 2830: 2831: 2832: 2833: 2834: 2835: 2836: 2837: 2838: 2839: 2840: 2841: 2842: 2843: 2844: 2845: 2846: 2847: 2848: 2849: 2850: 2851: 2852: 2853: 2854: 2855: 2856: 2857: 2858: 2859: 2860: 2861: 2862: 2863: 2864: 2865: 2866: 2867: 2868: 2869: 2870: 2871: 2872: 2873: 2874: 2875: 2876: 2877: 2878: 2879: 2880: 2881: 2882: 2883: 2884: 2885: 2886: 2887: 2888: 2889: 2890: 2891: 2892: 2893: 2894: 2895: 2896: 2897: 2898: 2899: 2900: 2901: 2902: 2903: 2904: 2905: 2906: 2907: 2908: 2909: 2910: 2911: 2912: 2913: 2914: 2915: 2916: 2917: 2918: 2919: 2920: 2921: 2922: 2923: 2924: 2925: 2926: 2927: 2928: 2929: 2930: 2931: 2932: 2933: 2934: 2935: 2936: 2937: 2938: 2939: 2940: 2941: 2942: 2943: 2944: 2945: 2946: 2947: 2948: 2949: 2950: 2951: 2952: 2953: 2954: 2955: 2956: 2957: 2958: 2959: 2960: 2961: 2962: 2963: 2964: 2965: 2966: 2967: 2968: 2969: 2970: 2971: 2972: 2973: 2974: 2975: 2976: 2977: 2978: 2979: 2980: 2981: 2982: 2983: 2984: 2985: 2986: 2987: 2988: 2989: 2990: 2991: 2992: 2993: 2994: 2995: 2996: 2997: 2998: 2999: 3000: 3001: 3002: 3003: 3004: 3005: 3006: 3007: 3008: 3009: 3010: 3011: 3012: 3013: 3014: 3015: 3016: 3017: 3018: 3019: 3020: 3021: 3022: 3023: 3024: 3025: 3026: 3027: 3028: 3029: 3030: 3031: 3032: 3033: 3034: 3035: 3036: 3037: 3038: 3039: 3040: 3041: 3042: 3043: 3044: 3045: 3046: 3047: 3048: 3049: 3050: 3051: 3052: 3053: 3054: 3055: 3056: 3057: 3058: 3059: 3060: 3061: 3062: 3063: 3064: 3065: 3066: 3067: 3068: 3069: 3070: 3071: 3072: 3073: 3074: 3075: 3076: 3077: 3078: 3079: 3080: 3081: 3082: 3083: 3084: 3085: 3086: 3087: 3088: 3089: 3090: 3091: 3092: 3093: 3094: 3095: 3096: 3097: 3098: 3099: 3100: 3101: 3102: 3103: 3104: 3105: 3106: 3107: 3108: 3109: 3110: 3111: 3112: 3113: 3114: 3115: 3116: 3117: 3118: 3119: 3120: 3121: 3122: 3123: 3124: 3125: 3126: 3127: 3128: 3129: 3130: 3131: 3132: 3133: 3134: 3135: 3136: 3137: 3138: 3139: 3140: 3141: 3142: 3143: 3144: 3145: 3146: 3147: 3148: 3149: 3150: 3151: 3152: 3153: 3154: 3155: 3156: 3157: 3158: 3159: 3160: 3161: 3162: 3163: 3164: 3165: 3166: 3167: 3168: 3169: 3170: 3171: 3172: 3173: 3174: 3175: 3176: 3177: 3178: 3179: 3180: 3181: 3182: 3183: 3184: 3185: 3186: 3187: 3188: 3189: 3190: 3191: 3192: 3193: 3194: 3195: 3196: 3197: 3198: 3199: 3200: 3201: 3202: 3203: 3204: 3205: 3206: 3207: 3208: 3209: 3210: 3211: 3212: 3213: 3214: 3215: 3216: 3217: 3218: 3219: 3220: 3221: 3222: 3223: 3224: 3225: 3226: 3227: 3228: 3229: 3230: 3231: 3232: 3233: 3234: 3235: 3236: 3237: 3238: 3239: 3240: 3241: 3242: 3243: 3244: 3245: 3246: 3247: 3248: 3249: 3250: 3251: 3252: 3253: 3254: 3255: 3256: 3257: 3258: 3259: 3260: 3261: 3262: 3263: 3264: 3265: 3266: 3267: 3268: 3269: 3270: 3271: 3272: 3273: 3274: 3275: 3276: 3277: 3278: 3279: 3280: 3281: 3282: 3283: 3284: 3285: 3286: 3287: 3288: 3289: 3290: 3291: 3292: 3293: 3294: 3295: 3296: 3297: 3298: 3299: 3300: 3301: 3302: 3303: 3304: 3305: 3306: 3307: 3308: 3309: 3310: 3311: 3312: 3313: 3314: 3315: 3316: 3317: 3318: 3319: 3320: 3321: 3322: 3323: 3324: 3325: 3326: 3327: 3328: 3329: 3330: 3331: 3332: 3333: 3334: 3335: 3336: 3337: 3338: 3339: 3340: 3341: 3342: 3343: 3344: 3345: 3346: 3347: 3348: 3349: 3350: 3351: 3352: 3353: 3354: 3355: 3356: 3357: 3358: 3359: 3360: 3361: 3362: 3363: 3364: 3365: 3366: 3367: 3368: 3369: 3370: 3371: 3372: 3373: 3374: 3375: 3376: 3377: 3378: 3379: 3380: 3381: 3382: 3383: 3384: 3385: 3386: 3387: 3388: 3389: 3390: 3391: 3392: 3393: 3394: 3395: 3396: 3397: 3398: 3399: 3400: 3401: 3402:
<?php
use Glpi\Cache\SimpleCache;
use Glpi\Exception\PasswordTooWeakException;
use PHPMailer\PHPMailer\PHPMailer;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;
use Zend\Cache\Storage\FlushableInterface;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
class Config extends CommonDBTM {
const DELETE_ALL = -1;
const KEEP_ALL = 0;
protected $displaylist = false;
public $auto_message_on_action = false;
public $showdebug = true;
static $rightname = 'config';
static $undisclosedFields = ['proxy_passwd', 'smtp_passwd'];
static function getTypeName($nb = 0) {
return __('Setup');
}
static function getMenuContent() {
$menu = [];
if (static::canView()) {
$menu['title'] = _x('setup', 'General');
$menu['page'] = Config::getFormURL(false);
$menu['options']['apiclient']['title'] = APIClient::getTypeName(Session::getPluralNumber());
$menu['options']['apiclient']['page'] = Config::getFormURL(false) . '?forcetab=Config$8';
$menu['options']['apiclient']['links']['search'] = Config::getFormURL(false) . '?forcetab=Config$8';
$menu['options']['apiclient']['links']['add'] = '/front/apiclient.form.php';
}
if (count($menu)) {
return $menu;
}
return false;
}
static function canCreate() {
return false;
}
function canViewItem() {
if (isset($this->fields['context']) &&
($this->fields['context'] == 'core' ||
Plugin::isPluginLoaded($this->fields['context']))) {
return true;
}
return false;
}
function defineTabs($options = []) {
$ong = [];
$this->addStandardTab(__CLASS__, $ong, $options);
$this->addStandardTab('Log', $ong, $options);
return $ong;
}
function prepareInputForUpdate($input) {
global $CFG_GLPI;
unset($input['_no_history']);
if (isset($input['context'])) {
return $input;
}
if (!empty($input['config_context'])) {
$config_context = $input['config_context'];
unset($input['id']);
unset($input['_glpi_csrf_token']);
unset($input['update']);
unset($input['config_context']);
if ((!empty($input['config_class']))
&& (class_exists($input['config_class']))
&& (method_exists ($input['config_class'], 'configUpdate'))) {
$config_method = $input['config_class'].'::configUpdate';
unset($input['config_class']);
$input = call_user_func($config_method, $input);
}
$this->setConfigurationValues($config_context, $input);
return false;
}
if (isset($input["url_base"]) && !empty($input["url_base"])) {
$input["url_base"] = rtrim($input["url_base"], '/');
}
if (isset($input['allow_search_view']) && !$input['allow_search_view']) {
$input['allow_search_global'] = 0;
}
if (isset($input["smtp_passwd"])) {
if (empty($input["smtp_passwd"])) {
unset($input["smtp_passwd"]);
} else {
$input["smtp_passwd"] = Toolbox::encrypt(stripslashes($input["smtp_passwd"]));
}
}
if (isset($input["_blank_smtp_passwd"]) && $input["_blank_smtp_passwd"]) {
$input['smtp_passwd'] = '';
}
if (isset($input["proxy_passwd"])) {
if (empty($input["proxy_passwd"])) {
unset($input["proxy_passwd"]);
} else {
$input["proxy_passwd"] = Toolbox::encrypt(stripslashes($input["proxy_passwd"]));
}
}
if (isset($input["_blank_proxy_passwd"]) && $input["_blank_proxy_passwd"]) {
$input['proxy_passwd'] = '';
}
if (isset($input['_dbslave_status'])) {
$already_active = DBConnection::isDBSlaveActive();
if ($input['_dbslave_status']) {
DBConnection::changeCronTaskStatus(true);
if (!$already_active) {
DBConnection::createDBSlaveConfig();
} else if (isset($input["_dbreplicate_dbhost"])) {
DBConnection::saveDBSlaveConf($input["_dbreplicate_dbhost"],
$input["_dbreplicate_dbuser"],
$input["_dbreplicate_dbpassword"],
$input["_dbreplicate_dbdefault"]);
}
}
if (!$input['_dbslave_status'] && $already_active) {
DBConnection::deleteDBSlaveConfig();
DBConnection::changeCronTaskStatus(false);
}
}
if (isset($input['_matrix'])) {
$tab = [];
for ($urgency=1; $urgency<=5; $urgency++) {
for ($impact=1; $impact<=5; $impact++) {
$priority = $input["_matrix_${urgency}_${impact}"];
$tab[$urgency][$impact] = $priority;
}
}
$input['priority_matrix'] = exportArrayToDB($tab);
$input['urgency_mask'] = 0;
$input['impact_mask'] = 0;
for ($i=1; $i<=5; $i++) {
if ($input["_urgency_${i}"]) {
$input['urgency_mask'] += (1<<$i);
}
if ($input["_impact_${i}"]) {
$input['impact_mask'] += (1<<$i);
}
}
}
if (isset( $input['lock_use_lock_item'])) {
$input['lock_item_list'] = exportArrayToDB((isset($input['lock_item_list'])
? $input['lock_item_list'] : []));
}
unset($input['id']);
unset($input['_glpi_csrf_token']);
unset($input['update']);
if (isset($input['maintenance_mode']) && $input['maintenance_mode']) {
$_SESSION['glpiskipMaintenance'] = 1;
$url = $CFG_GLPI['root_doc']."/index.php?skipMaintenance=1";
Session::addMessageAfterRedirect(sprintf(__('Maintenance mode activated. Backdoor using: %s'),
"<a href='$url'>$url</a>"),
false, WARNING);
}
$this->setConfigurationValues('core', $input);
return false;
}
static public function unsetUndisclosedFields(&$fields) {
if (isset($fields['context']) && isset($fields['name'])) {
if ($fields['context'] == 'core'
&& in_array($fields['name'], self::$undisclosedFields)) {
unset($fields['value']);
} else {
$fields = Plugin::doHookFunction('undiscloseConfigValue', $fields);
}
}
}
function showFormDisplay() {
global $CFG_GLPI;
if (!self::canView()) {
return;
}
$rand = mt_rand();
$canedit = Session::haveRight(self::$rightname, UPDATE);
if ($canedit) {
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
}
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('General setup') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='url_base'>" . __('URL of the application') . "</label></td>";
echo "<td colspan='3'><input type='text' name='url_base' id='url_base' size='80' value='".$CFG_GLPI["url_base"]."'>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='text_login'>" . __('Text in the login box (HTML tags supported)') . "</label></td>";
echo "<td colspan='3'>";
echo "<textarea cols='70' rows='4' name='text_login' id='text_login'>".$CFG_GLPI["text_login"]."</textarea>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td width='30%'><label for='dropdown_use_public_faq$rand'>" . __('Allow FAQ anonymous access') . "</label></td><td width='20%'>";
Dropdown::showYesNo("use_public_faq", $CFG_GLPI["use_public_faq"], -1, ['rand' => $rand]);
echo "</td><td width='30%'><label for='helpdesk_doc_url'>" . __('Simplified interface help link') . "</label></td>";
echo "<td><input size='22' type='text' name='helpdesk_doc_url' id='helpdesk_doc_url' value='" .
$CFG_GLPI["helpdesk_doc_url"] . "'></td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_list_limit_max$rand'>" . __('Default search results limit (page)')."</td><td>";
Dropdown::showNumber("list_limit_max", ['value' => $CFG_GLPI["list_limit_max"],
'min' => 5,
'max' => 200,
'step' => 5,
'rand' => $rand]);
echo "</td><td><label for='central_doc_url'>" . __('Standard interface help link') . "</label></td>";
echo "<td><input size='22' type='text' name='central_doc_url' id='central_doc_url' value='" .
$CFG_GLPI["central_doc_url"] . "'></td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='cut$rand'>" . __('Default characters limit (summary text boxes)') . "</label></td><td>";
echo Html::input('cut', [
'value' => $CFG_GLPI["cut"],
'id' => "cut$rand"
]);
echo "</td><td><label for='dropdown_url_maxlength$rand'>" . __('Default url length limit') . "</td><td>";
Dropdown::showNumber('url_maxlength', ['value' => $CFG_GLPI["url_maxlength"],
'min' => 20,
'max' => 80,
'step' => 5,
'rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_decimal_number$rand'>" .__('Default decimals limit') . "</label></td><td>";
Dropdown::showNumber("decimal_number", ['value' => $CFG_GLPI["decimal_number"],
'min' => 1,
'max' => 4,
'rand' => $rand]);
echo "</td>";
echo "<td colspan='2'></td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_translate_dropdowns$rand'>" . __("Translation of dropdowns") . "</label></td><td>";
Dropdown::showYesNo("translate_dropdowns", $CFG_GLPI["translate_dropdowns"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_translate_kb$rand'>" . __("Knowledge base translation") . "</label></td><td>";
Dropdown::showYesNo("translate_kb", $CFG_GLPI["translate_kb"], -1, ['rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_1'><td colspan='4' class='center b'>".__('Dynamic display').
"</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_dropdown_max$rand'>".
__('Page size for dropdown (paging using scroll)').
"</label></td><td>";
Dropdown::showNumber('dropdown_max', ['value' => $CFG_GLPI["dropdown_max"],
'min' => 1,
'max' => 200,
'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_use_ajax_autocompletion$rand'>" . __('Autocompletion of text fields') . "</label></td><td>";
Dropdown::showYesNo("use_ajax_autocompletion", $CFG_GLPI["use_ajax_autocompletion"], -1, ['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_ajax_limit_count$rand'>". __("Don't show search engine in dropdowns if the number of items is less than").
"</label></td><td>";
Dropdown::showNumber('ajax_limit_count', ['value' => $CFG_GLPI["ajax_limit_count"],
'min' => 1,
'max' => 200,
'step' => 1,
'toadd' => [0 => __('Never')],
'rand' => $rand]);
echo "<td colspan='2'></td>";
echo "</td></tr>";
echo "<tr class='tab_bg_1'><td colspan='4' class='center b'>".__('Search engine')."</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_allow_search_view$rand'>" . __('Items seen') . "</label></td><td>";
$values = [0 => __('No'),
1 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('last criterion')),
2 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('default criterion'))];
Dropdown::showFromArray('allow_search_view', $values,
['value' => $CFG_GLPI['allow_search_view'], 'rand' => $rand]);
echo "</td><td><label for='dropdown_allow_search_global$rand'>". __('Global search')."</label></td><td>";
if ($CFG_GLPI['allow_search_view']) {
Dropdown::showYesNo('allow_search_global', $CFG_GLPI['allow_search_global'], -1, ['rand' => $rand]);
} else {
echo Dropdown::getYesNo(0);
}
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_allow_search_all$rand'>" . __('All') . "</label></td><td>";
$values = [0 => __('No'),
1 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('last criterion'))];
Dropdown::showFromArray('allow_search_all', $values,
['value' => $CFG_GLPI['allow_search_all'], 'rand' => $rand]);
echo "</td><td colspan='2'></td></tr>";
echo "<tr class='tab_bg_1'><td colspan='4' class='center b'>".__('Item locks')."</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_lock_use_lock_item$rand'>" . __('Use locks') . "</label></td><td>";
Dropdown::showYesNo("lock_use_lock_item", $CFG_GLPI["lock_use_lock_item"], -1, ['rand' => $rand]);
echo "</td><td><label for='dropdown_lock_lockprofile_id$rand'>". __('Profile to be used when locking items')."</label></td><td>";
if ($CFG_GLPI["lock_use_lock_item"]) {
Profile::dropdown(['name' => 'lock_lockprofile_id',
'display_emptychoice' => true,
'value' => $CFG_GLPI['lock_lockprofile_id'],
'rand' => $rand]);
} else {
echo dropdown::getDropdownName(Profile::getTable(), $CFG_GLPI['lock_lockprofile_id']);
}
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_lock_item_list$rand'>" . __('List of items to lock') . "</label></td>";
echo "<td colspan=3>";
Dropdown::showFromArray('lock_item_list', ObjectLock::getLockableObjects(),
['values' => $CFG_GLPI['lock_item_list'],
'width' => '100%',
'multiple' => true,
'readonly' => !$CFG_GLPI["lock_use_lock_item"],
'rand' => $rand]);
echo "<tr class='tab_bg_1'><td colspan='4' class='center b'>".__('Auto Login').
"</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_login_remember_time$rand'>". __('Time to allow "Remember Me"').
"</label></td><td>";
Dropdown::showTimeStamp('login_remember_time', ['value' => $CFG_GLPI["login_remember_time"],
'emptylabel' => __('Disabled'),
'min' => 0,
'max' => MONTH_TIMESTAMP * 2,
'step' => DAY_TIMESTAMP,
'toadd' => [HOUR_TIMESTAMP, HOUR_TIMESTAMP * 2, HOUR_TIMESTAMP * 6, HOUR_TIMESTAMP * 12],
'rand' => $rand]);
echo "<td><label for='dropdown_login_remember_default$rand'>" . __("Default state of checkbox") . "</label></td><td>";
Dropdown::showYesNo("login_remember_default", $CFG_GLPI["login_remember_default"], -1, ['rand' => $rand]);
echo "</td>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_display_login_source$rand'>".
__('Display source dropdown on login page').
"</label></td><td>";
Dropdown::showYesNo("display_login_source", $CFG_GLPI["display_login_source"], -1, ['rand' => $rand]);
echo "</td><td colspan='2'></td></tr>";
if ($canedit) {
echo "<tr class='tab_bg_2'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
}
echo "</table></div>";
Html::closeForm();
}
function showFormInventory() {
global $CFG_GLPI;
if (!self::canView()) {
return;
}
$rand = mt_rand();
$canedit = Config::canUpdate();
if ($canedit) {
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
}
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('Assets') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td width='30%'><label for='dropdown_auto_create_infocoms$rand'>". __('Enable the financial and administrative information by default')."</label></td>";
echo "<td width='20%'>";
Dropdown::ShowYesNo('auto_create_infocoms', $CFG_GLPI["auto_create_infocoms"], -1, ['rand' => $rand]);
echo "</td><td width='20%'><label for='dropdown_monitors_management_restrict$rand'>" . __('Restrict monitor management') . "</label></td>";
echo "<td width='30%'>";
$this->dropdownGlobalManagement ("monitors_management_restrict",
$CFG_GLPI["monitors_management_restrict"],
$rand);
echo "</td></tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_softwarecategories_id_ondelete$rand'>" . __('Software category deleted by the dictionary rules') .
"</label></td><td>";
SoftwareCategory::dropdown(['value' => $CFG_GLPI["softwarecategories_id_ondelete"],
'name' => "softwarecategories_id_ondelete",
'rand' => $rand]);
echo "</td><td><label for='dropdown_peripherals_management_restrict$rand'>" . __('Restrict device management') . "</label></td><td>";
$this->dropdownGlobalManagement ("peripherals_management_restrict",
$CFG_GLPI["peripherals_management_restrict"],
$rand);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='showdate$rand'>" .__('End of fiscal year') . "</label></td><td>";
Html::showDateField("date_tax", ['value' => $CFG_GLPI["date_tax"],
'maybeempty' => false,
'canedit' => true,
'min' => '',
'max' => '',
'showyear' => false,
'rand' => $rand]);
echo "</td><td><label for='dropdown_phones_management_restrict$rand'>" . __('Restrict phone management') . "</label></td><td>";
$this->dropdownGlobalManagement ("phones_management_restrict",
$CFG_GLPI["phones_management_restrict"],
$rand);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_use_autoname_by_entity$rand'>" . __('Automatic fields (marked by *)') . "</label></td><td>";
$tab = [0 => __('Global'),
1 => __('By entity')];
Dropdown::showFromArray('use_autoname_by_entity', $tab,
['value' => $CFG_GLPI["use_autoname_by_entity"], 'rand' => $rand]);
echo "</td><td><label for='dropdown_printers_management_restrict$rand'>" . __('Restrict printer management') . "</label></td><td>";
$this->dropdownGlobalManagement("printers_management_restrict",
$CFG_GLPI["printers_management_restrict"],
$rand);
echo "</td></tr>";
echo "</table>";
if (Session::haveRightsOr("transfer", [CREATE, UPDATE])
&& Session::isMultiEntitiesMode()) {
echo "<br><table class='tab_cadre_fixe'>";
echo "<tr><th colspan='2'>" . __('Automatic transfer of computers') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_transfers_id_auto$rand'>" . __('Template for the automatic transfer of computers in another entity') .
"</label></td><td>";
Transfer::dropdown(['value' => $CFG_GLPI["transfers_id_auto"],
'name' => "transfers_id_auto",
'emptylabel' => __('No automatic transfer'),
'rand' => $rand]);
echo "</td></tr>";
echo "</table>";
}
echo "<br><table class='tab_cadre_fixe'>";
echo "<tr>";
echo "<th colspan='4'>".__('Automatically update of the elements related to the computers');
echo "</th><th colspan='2'>".__('Unit management')."</th></tr>";
echo "<tr><th> </th>";
echo "<th>" . __('Alternate username') . "</th>";
echo "<th>" . __('User') . "</th>";
echo "<th>" . __('Group') . "</th>";
echo "<th>" . __('Location') . "</th>";
echo "<th>" . __('Status') . "</th>";
echo "</tr>";
$fields = ["contact", "user", "group", "location"];
echo "<tr class='tab_bg_2'>";
echo "<td> " . __('When connecting or updating') . "</td>";
$values = [
__('Do not copy'),
__('Copy'),
];
foreach ($fields as $field) {
echo "<td>";
$fieldname = "is_".$field."_autoupdate";
Dropdown::showFromArray($fieldname, $values, ['value' => $CFG_GLPI[$fieldname]]);
echo "</td>";
}
echo "<td>";
State::dropdownBehaviour("state_autoupdate_mode", __('Copy computer status'),
$CFG_GLPI["state_autoupdate_mode"]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td> " . __('When disconnecting') . "</td>";
$values = [
__('Do not delete'),
__('Clear'),
];
foreach ($fields as $field) {
echo "<td>";
$fieldname = "is_".$field."_autoclean";
Dropdown::showFromArray($fieldname, $values, ['value' => $CFG_GLPI[$fieldname]]);
echo "</td>";
}
echo "<td>";
State::dropdownBehaviour("state_autoclean_mode", __('Clear status'),
$CFG_GLPI["state_autoclean_mode"]);
echo "</td></tr>";
if ($canedit) {
echo "<tr class='tab_bg_2'>";
echo "<td colspan='6' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
}
echo "</table></div>";
Html::closeForm();
}
function showFormAuthentication() {
global $CFG_GLPI;
if (!Config::canUpdate()) {
return;
}
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('Authentication') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td width='30%'>". __('Automatically add users from an external authentication source').
"</td><td width='20%'>";
Dropdown::showYesNo("is_users_auto_add", $CFG_GLPI["is_users_auto_add"]);
echo "</td><td width='30%'>". __('Add a user without accreditation from a LDAP directory').
"</td><td width='20%'>";
Dropdown::showYesNo("use_noright_users_add", $CFG_GLPI["use_noright_users_add"]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td> " . __('Action when a user is deleted from the LDAP directory') . "</td><td>";
AuthLDap::dropdownUserDeletedActions($CFG_GLPI["user_deleted_ldap"]);
echo "</td><td> " . __('GLPI server time zone') . "</td><td>";
Dropdown::showGMT("time_offset", $CFG_GLPI["time_offset"]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update_auth' class='submit' value=\""._sx('button', 'Save').
"\">";
echo "</td></tr>";
echo "</table></div>";
Html::closeForm();
}
function showFormDBSlave() {
global $DB, $CFG_GLPI, $DBslave;
if (!Config::canUpdate()) {
return;
}
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
echo "<div class='center' id='tabsbody'>";
echo "<input type='hidden' name='_dbslave_status' value='1'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr class='tab_bg_2'><th colspan='4'>" . _n('SQL replica', 'SQL replicas', Session::getPluralNumber()) .
"</th></tr>";
$DBslave = DBConnection::getDBSlaveConf();
if (is_array($DBslave->dbhost)) {
$host = implode(' ', $DBslave->dbhost);
} else {
$host = $DBslave->dbhost;
}
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('SQL server (MariaDB or MySQL)') . "</td>";
echo "<td><input type='text' name='_dbreplicate_dbhost' size='40' value='$host'></td>";
echo "<td>" . __('Database') . "</td>";
echo "<td><input type='text' name='_dbreplicate_dbdefault' value='".$DBslave->dbdefault."'>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('SQL user') . "</td>";
echo "<td><input type='text' name='_dbreplicate_dbuser' value='".$DBslave->dbuser."'></td>";
echo "<td>" . __('SQL password') . "</td>";
echo "<td><input type='password' name='_dbreplicate_dbpassword' value='".
rawurldecode($DBslave->dbpassword)."'>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('Use the slave for the search engine') . "</td><td>";
$values = [0 => __('Never'),
1 => __('If synced (all changes)'),
2 => __('If synced (current user changes)'),
3 => __('If synced or read-only account'),
4 => __('Always')];
Dropdown::showFromArray('use_slave_for_search', $values,
['value' => $CFG_GLPI["use_slave_for_search"]]);
echo "<td colspan='2'> </td>";
echo "</tr>";
if ($DBslave->connected && !$DB->isSlave()) {
echo "<tr class='tab_bg_2'><td colspan='4' class='center'>";
DBConnection::showAllReplicateDelay();
echo "</td></tr>";
}
echo "<tr class='tab_bg_2'><td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
echo "</table></div>";
Html::closeForm();
}
function showFormAPI() {
global $CFG_GLPI;
if (!self::canView()) {
return;
}
echo "<div class='center spaced' id='tabsbody'>";
$rand = mt_rand();
$canedit = Config::canUpdate();
if ($canedit) {
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
}
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('API') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='url_base_api'>" . __('URL of the API') . "</label></td>";
echo "<td colspan='3'><input type='text' name='url_base_api' id='url_base_api' size='80' value='".$CFG_GLPI["url_base_api"]."'></td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_enable_api$rand'>" . __("Enable Rest API") . "</label></td>";
echo "<td>";
Dropdown::showYesNo("enable_api", $CFG_GLPI["enable_api"], -1, ['rand' => $rand]);
echo "</td>";
if ($CFG_GLPI["enable_api"]) {
echo "<td colspan='2'>";
$inline_doc_api = trim($CFG_GLPI['url_base_api'], '/')."/";
echo "<a href='$inline_doc_api'>".__("API inline Documentation")."</a>";
echo "</td>";
}
echo "</tr>";
echo "<tr><th colspan='4'>" . __('Authentication') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_enable_api_login_credentials$rand'>";
echo __("Enable login with credentials")."</label> ";
Html::showToolTip(__("Allow to login to API and get a session token with user credentials"));
echo "</td>";
echo "<td>";
Dropdown::showYesNo("enable_api_login_credentials", $CFG_GLPI["enable_api_login_credentials"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_enable_api_login_external_token$rand'>";
echo __("Enable login with external token")."</label> ";
Html::showToolTip(__("Allow to login to API and get a session token with user external token. See Remote access key in user Settings tab "));
echo "</td>";
echo "<td>";
Dropdown::showYesNo("enable_api_login_external_token", $CFG_GLPI["enable_api_login_external_token"], -1, ['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'><td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "<br><br><br>";
echo "</td></tr>";
echo "</table>";
Html::closeForm();
echo "<table class='tab_cadre_fixe'>";
echo "<tr><td>";
echo "<hr>";
$buttons = [
'apiclient.form.php' => __('Add API client'),
];
Html::displayTitle("",
self::getTypeName(Session::getPluralNumber()),
"",
$buttons);
Search::show("APIClient");
echo "</td></tr>";
echo "</table></div>";
}
function showFormHelpdesk() {
global $CFG_GLPI;
if (!self::canView()) {
return;
}
$rand = mt_rand();
$canedit = Config::canUpdate();
if ($canedit) {
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
}
echo "<div class='center spaced' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('Assistance') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td width='30%'><label for='dropdown_time_step$rand'>" . __('Step for the hours (minutes)') . "</label></td>";
echo "<td width='20%'>";
Dropdown::showNumber('time_step', ['value' => $CFG_GLPI["time_step"],
'min' => 30,
'max' => 60,
'step' => 30,
'toadd' => [1 => 1,
5 => 5,
10 => 10,
15 => 15,
20 => 20],
'rand' => $rand]);
echo "</td>";
echo "<td width='30%'><label for='dropdown_planning_begin$rand'>" .__('Limit of the schedules for planning') . "</label></td>";
echo "<td width='20%'>";
Dropdown::showHours('planning_begin', ['value' => $CFG_GLPI["planning_begin"], 'rand' => $rand]);
echo " <label for='dropdown_planning_end$rand'>-></label> ";
Dropdown::showHours('planning_end', ['value' => $CFG_GLPI["planning_end"], 'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_default_mailcollector_filesize_max$rand'>".__('Default file size limit imported by the mails receiver')."</label></td><td>";
MailCollector::showMaxFilesize('default_mailcollector_filesize_max',
$CFG_GLPI["default_mailcollector_filesize_max"],
$rand);
echo "</td>";
echo "<td><label for='dropdown_documentcategories_id_forticket$rand'>" . __('Default heading when adding a document to a ticket') . "</label></td><td>";
DocumentCategory::dropdown(['value' => $CFG_GLPI["documentcategories_id_forticket"],
'name' => "documentcategories_id_forticket",
'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_default_software_helpdesk_visible$rand'>" . __('By default, a software may be linked to a ticket') . "</label></td><td>";
Dropdown::showYesNo("default_software_helpdesk_visible",
$CFG_GLPI["default_software_helpdesk_visible"],
-1,
['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_keep_tickets_on_delete$rand'>" . __('Keep tickets when purging hardware in the inventory') . "</label></td><td>";
Dropdown::showYesNo("keep_tickets_on_delete", $CFG_GLPI["keep_tickets_on_delete"], -1, ['rand' => $rand]);
echo "</td></tr><tr class='tab_bg_2'><td><label for='dropdown_use_check_pref$rand'>".__('Show personnal information in new ticket form (simplified interface)');
echo "</label></td>";
echo "<td>";
Dropdown::showYesNo('use_check_pref', $CFG_GLPI['use_check_pref'], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_use_anonymous_helpdesk$rand'>" .__('Allow anonymous ticket creation (helpdesk.receiver)') . "</label></td><td>";
Dropdown::showYesNo("use_anonymous_helpdesk", $CFG_GLPI["use_anonymous_helpdesk"], -1, ['rand' => $rand]);
echo "</td></tr><tr class='tab_bg_2'><td><label for='dropdown_use_anonymous_followups$rand'>" . __('Allow anonymous followups (receiver)') . "</label></td><td>";
Dropdown::showYesNo("use_anonymous_followups", $CFG_GLPI["use_anonymous_followups"], -1, ['rand' => $rand]);
echo "</td><td colspan='2'></td></tr>";
echo "</table>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='7'>" . __('Matrix of calculus for priority');
echo "<input type='hidden' name='_matrix' value='1'></th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td class='b right' colspan='2'>".__('Impact')."</td>";
$isimpact = [];
for ($impact=5; $impact>=1; $impact--) {
echo "<td class='center'>".Ticket::getImpactName($impact).'<br>';
if ($impact==3) {
$isimpact[3] = 1;
echo "<input type='hidden' name='_impact_3' value='1'>";
} else {
$isimpact[$impact] = (($CFG_GLPI['impact_mask']&(1<<$impact)) >0);
Dropdown::showYesNo("_impact_${impact}", $isimpact[$impact]);
}
echo "</td>";
}
echo "</tr>";
echo "<tr class='tab_bg_1'>";
echo "<td class='b' colspan='2'>".__('Urgency')."</td>";
for ($impact=5; $impact>=1; $impact--) {
echo "<td> </td>";
}
echo "</tr>";
$isurgency = [];
for ($urgency=5; $urgency>=1; $urgency--) {
echo "<tr class='tab_bg_1'>";
echo "<td>".Ticket::getUrgencyName($urgency)." </td>";
echo "<td>";
if ($urgency==3) {
$isurgency[3] = 1;
echo "<input type='hidden' name='_urgency_3' value='1'>";
} else {
$isurgency[$urgency] = (($CFG_GLPI['urgency_mask']&(1<<$urgency)) >0);
Dropdown::showYesNo("_urgency_${urgency}", $isurgency[$urgency]);
}
echo "</td>";
for ($impact=5; $impact>=1; $impact--) {
$pri = round(($urgency+$impact)/2);
if (isset($CFG_GLPI['priority_matrix'][$urgency][$impact])) {
$pri = $CFG_GLPI['priority_matrix'][$urgency][$impact];
}
if ($isurgency[$urgency] && $isimpact[$impact]) {
$bgcolor=$_SESSION["glpipriority_$pri"];
echo "<td class='center' bgcolor='$bgcolor'>";
Ticket::dropdownPriority(['value' => $pri,
'name' => "_matrix_${urgency}_${impact}"]);
echo "</td>";
} else {
echo "<td><input type='hidden' name='_matrix_${urgency}_${impact}' value='$pri'>
</td>";
}
}
echo "</tr>\n";
}
if ($canedit) {
echo "<tr class='tab_bg_2'>";
echo "<td colspan='7' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
}
echo "</table></div>";
Html::closeForm();
}
function showFormUserPrefs($data = []) {
global $CFG_GLPI;
$oncentral = (Session::getCurrentInterface() == "central");
$userpref = false;
$url = Toolbox::getItemTypeFormURL(__CLASS__);
$rand = mt_rand();
$canedit = Config::canUpdate();
$canedituser = Session::haveRight('personalization', UPDATE);
if (array_key_exists('last_login', $data)) {
$userpref = true;
if ($data["id"] === Session::getLoginUserID()) {
$url = $CFG_GLPI['root_doc']."/front/preference.php";
} else {
$url = User::getFormURL();
}
}
if ((!$userpref && $canedit) || ($userpref && $canedituser)) {
echo "<form name='form' action='$url' method='post'>";
}
if ($userpref) {
echo "<input type='hidden' name='id' value='".$data['id']."'>";
}
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('Personalization') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td width='30%'><label for='dropdown_language$rand'>" . ($userpref?__('Language'):__('Default language')) . "</label></td>";
echo "<td width='20%'>";
if (Config::canUpdate()
|| !GLPI_DEMO_MODE) {
Dropdown::showLanguages("language", ['value' => $data["language"], 'rand' => $rand]);
} else {
echo " ";
}
echo "<td width='30%'><label for='dropdown_date_format$rand'>" . __('Date format') ."</label></td>";
echo "<td width='20%'>";
Dropdown::showFromArray('date_format', Toolbox::phpDateFormats(), ['value' => $data["date_format"], 'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_names_format$rand'>".__('Display order of surnames firstnames')."</label></td><td>";
$values = [User::REALNAME_BEFORE => __('Surname, First name'),
User::FIRSTNAME_BEFORE => __('First name, Surname')];
Dropdown::showFromArray('names_format', $values, ['value' => $data["names_format"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_number_format$rand'>" .__('Number format') . "</label></td>";
$values = [0 => '1 234.56',
1 => '1,234.56',
2 => '1 234,56',
3 => '1234.56',
4 => '1234,56'];
echo "<td>";
Dropdown::showFromArray('number_format', $values, ['value' => $data["number_format"], 'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_list_limit$rand'>" . __('Results to display by page')."</label></td><td>";
$value = (($data['list_limit'] < $CFG_GLPI['list_limit_max'])
? $data['list_limit'] : $CFG_GLPI['list_limit_max']);
Dropdown::showNumber('list_limit', ['value' => $value,
'min' => 5,
'max' => $CFG_GLPI['list_limit_max'],
'step' => 5,
'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_backcreated$rand'>".__('Go to created item after creation')."</label></td>";
echo "<td>";
Dropdown::showYesNo("backcreated", $data["backcreated"], -1, ['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
if ($oncentral) {
echo "<td><label for='dropdown_use_flat_dropdowntree$rand'>" . __('Display the complete name in tree dropdowns') . "</label></td><td>";
Dropdown::showYesNo('use_flat_dropdowntree', $data["use_flat_dropdowntree"], -1, ['rand' => $rand]);
echo "</td>";
} else {
echo "<td colspan='2'> </td>";
}
if (!$userpref
|| ($CFG_GLPI['show_count_on_tabs'] != -1)) {
echo "<td><label for='dropdown_show_count_on_tabs$rand'>".__('Display counters')."</label></td><td>";
$values = [0 => __('No'),
1 => __('Yes')];
if (!$userpref) {
$values[-1] = __('Never');
}
Dropdown::showFromArray('show_count_on_tabs', $values,
['value' => $data["show_count_on_tabs"], 'rand' => $rand]);
echo "</td>";
} else {
echo "<td colspan='2'> </td>";
}
echo "</tr>";
echo "<tr class='tab_bg_2'>";
if ($oncentral) {
echo "<td><label for='dropdown_is_ids_visible$rand'>" . __('Show GLPI ID') . "</label></td><td>";
Dropdown::showYesNo("is_ids_visible", $data["is_ids_visible"], -1, ['rand' => $rand]);
echo "</td>";
} else {
echo "<td colspan='2'></td>";
}
echo "<td><label for='dropdown_keep_devices_when_purging_item$rand'>" . __('Keep devices when purging an item') . "</label></td><td>";
Dropdown::showYesNo('keep_devices_when_purging_item',
$data['keep_devices_when_purging_item'],
-1,
['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_notification_to_myself$rand'>" . __('Notifications for my changes') . "</label></td><td>";
Dropdown::showYesNo("notification_to_myself", $data["notification_to_myself"], -1, ['rand' => $rand]);
echo "</td>";
if ($oncentral) {
echo "<td><label for='dropdown_display_count_on_home$rand'>".__('Results to display on home page')."</label></td><td>";
Dropdown::showNumber('display_count_on_home',
['value' => $data['display_count_on_home'],
'min' => 0,
'max' => 30,
'rand' => $rand]);
echo "</td>";
} else {
echo "<td colspan='2'> </td>";
}
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_pdffont$rand'>" . __('PDF export font') . "</label></td><td>";
Dropdown::showFromArray("pdffont", GLPIPDF::getFontList(),
['value' => $data["pdffont"],
'width' => 200,
'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_csv_delimiter$rand'>".__('CSV delimiter')."</label></td><td>";
$values = [';' => ';',
',' => ','];
Dropdown::showFromArray('csv_delimiter', $values, ['value' => $data["csv_delimiter"], 'rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='theme-selector'>" . __("Color palette") . "</label></td><td>";
echo Html::select(
'palette',
$this->getPalettes(),
[
'id' => 'theme-selector',
'selected' => $data['palette']
]
);
echo Html::scriptBlock("
function formatThemes(theme) {
if (!theme.id) {
return theme.text;
}
return $('<span></span>').html('<img src=\'../css/palettes/previews/' + theme.text.toLowerCase() + '.png\'/>'
+ ' ' + theme.text);
}
$(\"#theme-selector\").select2({
templateResult: formatThemes,
templateSelection: formatThemes,
width: '100%',
escapeMarkup: function(m) { return m; }
});
$('label[for=theme-selector]').on('click', function(){ $('#theme-selector').select2('open'); });
");
echo "</td>";
echo "<td><label for='layout-selector'>" . __('Layout')."</label></td><td>";
$layout_options = [
'lefttab' => __("Tabs on left"),
'classic' => __("Classic view"),
'vsplit' => __("Vertical split")
];
echo Html::select(
'layout',
$layout_options,
[
'id' => 'layout-selector',
'selected' => $data['layout']
]
);
echo Html::scriptBlock("
function formatLayout(layout) {
if (!layout.id) {
return layout.text;
}
return $('<span></span>').html('<img src=\'../pics/layout_' + layout.id.toLowerCase() + '.png\'/>'
+ ' ' + layout.text);
}
$(\"#layout-selector\").select2({
dropdownAutoWidth: true,
templateResult: formatLayout,
templateSelection: formatLayout
});
$('label[for=layout-selector]').on('click', function(){ $('#layout-selector').select2('open'); });
");
echo "</select>";
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_highcontrast_css$rand'>".__('Enable high contrast')."</label></td>";
echo "<td>";
Dropdown::showYesNo('highcontrast_css', $data['highcontrast_css'], -1, ['rand' => $rand]);
echo "</td>";
echo "<td colspan='2'>";
echo "</td></tr>";
if ($oncentral) {
echo "<tr class='tab_bg_1'><th colspan='4'>".__('Assistance')."</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_followup_private$rand'>".__('Private followups by default')."</label></td><td>";
Dropdown::showYesNo("followup_private", $data["followup_private"], -1, ['rand' => $rand]);
echo "</td><td><label for='dropdown_show_jobs_at_login$rand'>". __('Show new tickets on the home page') . "</label></td><td>";
if (Session::haveRightsOr("ticket",
[Ticket::READMY, Ticket::READALL, Ticket::READASSIGN])) {
Dropdown::showYesNo("show_jobs_at_login", $data["show_jobs_at_login"], -1, ['rand' => $rand]);
} else {
echo Dropdown::getYesNo(0);
}
echo " </td></tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_task_private$rand'>" . __('Private tasks by default') . "</label></td><td>";
Dropdown::showYesNo("task_private", $data["task_private"], -1, ['rand' => $rand]);
echo "</td><td><label for='dropdown_default_requesttypes_id$rand'>" . __('Request sources by default') . "</label></td><td>";
RequestType::dropdown([
'value' => $data["default_requesttypes_id"],
'name' => "default_requesttypes_id",
'condition' => ['is_active' => 1, 'is_ticketheader' => 1],
'rand' => $rand
]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_task_state$rand'>" . __('Tasks state by default') . "</label></td><td>";
Planning::dropdownState("task_state", $data["task_state"], true, ['rand' => $rand]);
echo "</td><td><label for='dropdown_refresh_ticket_list$rand'>" . __('Automatically refresh the list of tickets (minutes)') . "</label></td><td>";
Dropdown::showNumber('refresh_ticket_list', ['value' => $data["refresh_ticket_list"],
'min' => 1,
'max' => 30,
'step' => 1,
'toadd' => [0 => __('Never')],
'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'><td><label for='dropdown_set_default_tech$rand'>".__('Pre-select me as a technician when creating a ticket').
"</label></td><td>";
if (!$userpref || Session::haveRight('ticket', Ticket::OWN)) {
Dropdown::showYesNo("set_default_tech", $data["set_default_tech"], -1, ['rand' => $rand]);
} else {
echo Dropdown::getYesNo(0);
}
echo "</td><td><label for='dropdown_set_default_requester$rand'>" . __('Pre-select me as a requester when creating a ticket') . "</label></td><td>";
if (!$userpref || Session::haveRight('ticket', CREATE)) {
Dropdown::showYesNo("set_default_requester", $data["set_default_requester"], -1, ['rand' => $rand]);
} else {
echo Dropdown::getYesNo(0);
}
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('Priority colors') . "</td>";
echo "<td colspan='3'>";
echo "<table><tr>";
echo "<td><label for='dropdown_priority_1$rand'>1</label> ";
Html::showColorField('priority_1', ['value' => $data["priority_1"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_priority_2$rand'>2</label> ";
Html::showColorField('priority_2', ['value' => $data["priority_2"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_priority_3$rand'>3</label> ";
Html::showColorField('priority_3', ['value' => $data["priority_3"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_priority_4$rand'>4</label> ";
Html::showColorField('priority_4', ['value' => $data["priority_4"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_priority_5$rand'>5</label> ";
Html::showColorField('priority_5', ['value' => $data["priority_5"], 'rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_priority_6$rand'>6</label> ";
Html::showColorField('priority_6', ['value' => $data["priority_6"], 'rand' => $rand]);
echo "</td>";
echo "</tr></table>";
echo "</td></tr>";
}
echo "<tr><th colspan='4'>".__('Due date progression')."</th></tr>";
echo "<tr class='tab_bg_1'>".
"<td>".__('OK state color')."</td>";
echo "<td>";
Html::showColorField('duedateok_color', ['value' => $data["duedateok_color"]]);
echo "</td><td colspan='2'> </td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td>".__('Warning state color')."</td>";
echo "<td>";
Html::showColorField('duedatewarning_color', ['value' => $data["duedatewarning_color"]]);
echo "</td>";
echo "<td>".__('Warning state threshold')."</td>";
echo "<td>";
Dropdown::showNumber("duedatewarning_less", ['value' => $data['duedatewarning_less']]);
$elements = ['%' => '%',
'hours' => _n('Hour', 'Hours', Session::getPluralNumber()),
'days' => _n('Day', 'Days', Session::getPluralNumber())];
echo " ";
Dropdown::showFromArray("duedatewarning_unit", $elements,
['value' => $data['duedatewarning_unit']]);
echo "</td></tr>";
echo "<tr class='tab_bg_1'>".
"<td>".__('Critical state color')."</td>";
echo "<td>";
Html::showColorField('duedatecritical_color', ['value' => $data["duedatecritical_color"]]);
echo "</td>";
echo "<td>".__('Critical state threshold')."</td>";
echo "<td>";
Dropdown::showNumber("duedatecritical_less", ['value' => $data['duedatecritical_less']]);
echo " ";
$elements = ['%' => '%',
'hours' => _n('Hour', 'Hours', Session::getPluralNumber()),
'days' => _n('Day', 'Days', Session::getPluralNumber())];
Dropdown::showFromArray("duedatecritical_unit", $elements,
['value' => $data['duedatecritical_unit']]);
echo "</td></tr>";
if ($oncentral && $CFG_GLPI["lock_use_lock_item"]) {
echo "<tr class='tab_bg_1'><th colspan='4' class='center b'>".__('Item locks')."</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td>" . __('Auto-lock Mode') . "</td><td>";
Dropdown::showYesNo("lock_autolock_mode", $data["lock_autolock_mode"]);
echo "</td><td>". __('Direct Notification (requester for unlock will be the notification sender)').
"</td><td>";
Dropdown::showYesNo("lock_directunlock_notification", $data["lock_directunlock_notification"]);
echo "</td></tr>";
}
if ((!$userpref && $canedit) || ($userpref && $canedituser)) {
echo "<tr class='tab_bg_2'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
}
echo "</table></div>";
Html::closeForm();
}
static function displayPasswordSecurityChecks($field = 'password') {
global $CFG_GLPI;
$needs = [];
if ($CFG_GLPI["use_password_security"]) {
printf(__('%1$s: %2$s'), __('Password minimum length'),
"<span id='password_min_length' class='red'>".$CFG_GLPI['password_min_length'].
"</span>");
}
echo "<script type='text/javascript' >\n";
echo "function passwordCheck() {\n";
if ($CFG_GLPI["use_password_security"]) {
echo "var pwd = ".Html::jsGetElementbyID($field).";";
echo "if (pwd.val().length < ".$CFG_GLPI['password_min_length'].") {
".Html::jsGetElementByID('password_min_length').".addClass('red');
".Html::jsGetElementByID('password_min_length').".removeClass('green');
} else {
".Html::jsGetElementByID('password_min_length').".addClass('green');
".Html::jsGetElementByID('password_min_length').".removeClass('red');
}";
if ($CFG_GLPI["password_need_number"]) {
$needs[] = "<span id='password_need_number' class='red'>".__('Digit')."</span>";
echo "var numberRegex = new RegExp('[0-9]', 'g');
if (false == numberRegex.test(pwd.val())) {
".Html::jsGetElementByID('password_need_number').".addClass('red');
".Html::jsGetElementByID('password_need_number').".removeClass('green');
} else {
".Html::jsGetElementByID('password_need_number').".addClass('green');
".Html::jsGetElementByID('password_need_number').".removeClass('red');
}";
}
if ($CFG_GLPI["password_need_letter"]) {
$needs[] = "<span id='password_need_letter' class='red'>".__('Lowercase')."</span>";
echo "var letterRegex = new RegExp('[a-z]', 'g');
if (false == letterRegex.test(pwd.val())) {
".Html::jsGetElementByID('password_need_letter').".addClass('red');
".Html::jsGetElementByID('password_need_letter').".removeClass('green');
} else {
".Html::jsGetElementByID('password_need_letter').".addClass('green');
".Html::jsGetElementByID('password_need_letter').".removeClass('red');
}";
}
if ($CFG_GLPI["password_need_caps"]) {
$needs[] = "<span id='password_need_caps' class='red'>".__('Uppercase')."</span>";
echo "var capsRegex = new RegExp('[A-Z]', 'g');
if (false == capsRegex.test(pwd.val())) {
".Html::jsGetElementByID('password_need_caps').".addClass('red');
".Html::jsGetElementByID('password_need_caps').".removeClass('green');
} else {
".Html::jsGetElementByID('password_need_caps').".addClass('green');
".Html::jsGetElementByID('password_need_caps').".removeClass('red');
}";
}
if ($CFG_GLPI["password_need_symbol"]) {
$needs[] = "<span id='password_need_symbol' class='red'>".__('Symbol')."</span>";
echo "var capsRegex = new RegExp('[^a-zA-Z0-9_]', 'g');
if (false == capsRegex.test(pwd.val())) {
".Html::jsGetElementByID('password_need_symbol').".addClass('red');
".Html::jsGetElementByID('password_need_symbol').".removeClass('green');
} else {
".Html::jsGetElementByID('password_need_symbol').".addClass('green');
".Html::jsGetElementByID('password_need_symbol').".removeClass('red');
}";
}
}
echo "}";
echo '</script>';
if (count($needs)) {
echo "<br>";
printf(__('%1$s: %2$s'), __('Password must contains'), implode(', ', $needs));
}
}
static function validatePassword($password, $display = true) {
global $CFG_GLPI;
$ok = true;
$exception = new PasswordTooWeakException();
if ($CFG_GLPI["use_password_security"]) {
if (Toolbox::strlen($password) < $CFG_GLPI['password_min_length']) {
$ok = false;
if ($display) {
Session::addMessageAfterRedirect(__('Password too short!'), false, ERROR);
} else {
$exception->addMessage(__('Password too short!'));
}
}
if ($CFG_GLPI["password_need_number"]
&& !preg_match("/[0-9]+/", $password)) {
$ok = false;
if ($display) {
Session::addMessageAfterRedirect(__('Password must include at least a digit!'),
false, ERROR);
} else {
$exception->addMessage(__('Password must include at least a digit!'));
}
}
if ($CFG_GLPI["password_need_letter"]
&& !preg_match("/[a-z]+/", $password)) {
$ok = false;
if ($display) {
Session::addMessageAfterRedirect(__('Password must include at least a lowercase letter!'),
false, ERROR);
} else {
$exception->addMessage(__('Password must include at least a lowercase letter!'));
}
}
if ($CFG_GLPI["password_need_caps"]
&& !preg_match("/[A-Z]+/", $password)) {
$ok = false;
if ($display) {
Session::addMessageAfterRedirect(__('Password must include at least a uppercase letter!'),
false, ERROR);
} else {
$exception->addMessage(__('Password must include at least a uppercase letter!'));
}
}
if ($CFG_GLPI["password_need_symbol"]
&& !preg_match("/\W+/", $password)) {
$ok = false;
if ($display) {
Session::addMessageAfterRedirect(__('Password must include at least a symbol!'),
false, ERROR);
} else {
$exception->addMessage(__('Password must include at least a symbol!'));
}
}
}
if (!$ok && !$display) {
throw $exception;
}
return $ok;
}
function showPerformanceInformations() {
$GLPI_CACHE = self::getCache('cache_db', 'core', false);
if (!Config::canUpdate()) {
return false;
}
echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('PHP opcode cache') . "</th></tr>";
$ext = 'Zend OPcache';
if (extension_loaded($ext) && ($info = opcache_get_status(false))) {
$msg = sprintf(__s('%s extension is installed'), $ext);
echo "<tr><td>" . sprintf(__('The "%s" extension is installed'), $ext) . "</td>
<td>" . phpversion($ext) . "</td>
<td></td>
<td class='icons_block'><i class='fa fa-check-circle ok' title='$msg'><span class='sr-only'>$msg</span></td></tr>";
$used = $info['memory_usage']['used_memory'];
$free = $info['memory_usage']['free_memory'];
$rate = round(100.0 * $used / ($used + $free));
$max = Toolbox::getSize($used + $free);
$used = Toolbox::getSize($used);
echo "<tr><td>" . __('Memory') . "</td>
<td>" . sprintf(__('%1$s / %2$s'), $used, $max) . "</td><td>";
Html::displayProgressBar('100', $rate, ['simple' => true,
'forcepadding' => false]);
$class = 'info-circle missing';
$msg = sprintf(__s('%1$s memory usage is too low or too high'), $ext);
if ($rate > 5 && $rate < 75) {
$class = 'check-circle ok';
$msg = sprintf(__s('%1$s memory usage is correct'), $ext);
}
echo "</td><td class='icons_block'><i title='$msg' class='fa fa-$class'></td></tr>";
$hits = $info['opcache_statistics']['hits'];
$miss = $info['opcache_statistics']['misses'];
$max = $hits+$miss;
$rate = round($info['opcache_statistics']['opcache_hit_rate']);
echo "<tr><td>" . __('Hits rate') . "</td>
<td>" . sprintf(__('%1$s / %2$s'), $hits, $max) . "</td><td>";
Html::displayProgressBar('100', $rate, ['simple' => true,
'forcepadding' => false]);
$class = 'info-circle missing';
$msg = sprintf(__s('%1$s hits rate is low'), $ext);
if ($rate > 90) {
$class = 'check-circle ok';
$msg = sprintf(__s('%1$s hits rate is correct'), $ext);
}
echo "</td><td class='icons_block'><i title='$msg' class='fa fa-$class'></td></tr>";
$max = $info['opcache_statistics']['oom_restarts'];
echo "<tr><td>" . __('Out of memory restart') . "</td>
<td>$max</td><td>";
$class = 'info-circle missing';
$msg = sprintf(__s('%1$s restart rate is too high'), $ext);
if ($max < 2) {
$class = 'check-circle ok';
$msg = sprintf(__s('%1$s restart rate is correct'), $ext);
}
echo "</td><td class='icons_block'><i title='$msg' class='fa fa-$class'></td></tr>";
if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) {
echo "<tr><td></td><td colspan='3'>";
echo "<a class='vsubmit' href='config.form.php?reset_opcache=1'>";
echo __('Reset');
echo "</a></td></tr>\n";
}
} else {
$msg = sprintf(__s('%s extension is not present'), $ext);
echo "<tr><td colspan='3'>" . sprintf(__('Installing and enabling the "%s" extension may improve GLPI performance'), $ext) . "</td>
<td class='icons_block'><i class='fa fa-info-circle missing' title='$msg'></i><span class='sr-only'>$msg</span></td></tr>";
}
echo "<tr><th colspan='4'>" . __('User data cache') . "</th></tr>";
if (Toolbox::useCache()) {
$ext = strtolower(get_class($GLPI_CACHE));
$ext = substr($ext, strrpos($ext, '\\')+1);
if (in_array($ext, ['apcu', 'memcache', 'memcached', 'wincache', 'redis'])) {
$msg = sprintf(__s('The "%s" cache extension is installed'), $ext);
} else {
$msg = sprintf(__s('"%s" cache system is used'), $ext);
}
echo "<tr><td>" . $msg . "</td>
<td>" . phpversion($ext) . "</td>
<td></td>
<td class='icons_block'><i class='fa fa-check-circle ok' title='$msg'></i><span class='sr-only'>$msg</span></td></tr>";
if ($ext != 'filesystem' && $GLPI_CACHE instanceof AvailableSpaceCapableInterface && $GLPI_CACHE instanceof TotalSpaceCapableInterface) {
$free = $GLPI_CACHE->getAvailableSpace();
$max = $GLPI_CACHE->getTotalSpace();
$used = $max - $free;
$rate = round(100.0 * $used / $max);
$max = Toolbox::getSize($max);
$used = Toolbox::getSize($used);
echo "<tr><td>" . __('Memory') . "</td>
<td>" . sprintf(__('%1$s / %2$s'), $used, $max) . "</td><td>";
Html::displayProgressBar('100', $rate, ['simple' => true,
'forcepadding' => false]);
$class = 'info-circle missing';
$msg = sprintf(__s('%1$s memory usage is too high'), $ext);
if ($rate < 80) {
$class = 'check-circle ok';
$msg = sprintf(__s('%1$s memory usage is correct'), $ext);
}
echo "</td><td class='icons_block'><i title='$msg' class='fa fa-$class'></td></tr>";
}
if ($GLPI_CACHE instanceof FlushableInterface) {
if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) {
echo "<tr><td></td><td colspan='3'>";
echo "<a class='vsubmit' href='config.form.php?reset_cache=1'>";
echo __('Reset');
echo "</a></td></tr>\n";
}
}
} else {
$ext = 'APCu';
$msg = sprintf(__s('%s extension is not present'), $ext);
echo "<tr><td colspan='3'>" . sprintf(__('Installing the "%s" extension may improve GLPI performance'), $ext) . "</td>
<td><i class='fa fa-info-circle missing' title='$msg'></i><span class='sr-only'>$msg</span></td></tr>";
}
echo "</table></div>\n";
}
function showSystemInformations() {
global $DB, $CFG_GLPI;
if (!Config::canUpdate()) {
return false;
}
$rand = mt_rand();
echo "<div class='center' id='tabsbody'>";
echo "<form name='form' action=\"".Toolbox::getItemTypeFormURL(__CLASS__)."\" method='post'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('General setup') . "</th></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_event_loglevel$rand'>" . __('Log Level') . "</label></td><td>";
$values = [
1 => __('1- Critical (login error only)'),
2 => __('2- Severe (not used)'),
3 => __('3- Important (successful logins)'),
4 => __('4- Notices (add, delete, tracking)'),
5 => __('5- Complete (all)'),
];
Dropdown::showFromArray('event_loglevel', $values,
['value' => $CFG_GLPI["event_loglevel"], 'rand' => $rand]);
echo "</td><td><label for='dropdown_cron_limit$rand'>".__('Maximal number of automatic actions (run by CLI)')."</label></td><td>";
Dropdown::showNumber('cron_limit', ['value' => $CFG_GLPI["cron_limit"],
'min' => 1,
'max' => 30,
'rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_use_log_in_files$rand'>" . __('Logs in files (SQL, email, automatic action...)') . "</label></td><td>";
Dropdown::showYesNo("use_log_in_files", $CFG_GLPI["use_log_in_files"], -1, ['rand' => $rand]);
echo "</td><td><label for='dropdown__dbslave_status$rand'>" . _n('SQL replica', 'SQL replicas', 1) . "</label></td><td>";
$active = DBConnection::isDBSlaveActive();
Dropdown::showYesNo("_dbslave_status", $active, -1, ['rand' => $rand]);
echo "</td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4' class='center b'>".__('Password security policy');
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_use_password_security$rand'>" . __('Password security policy validation') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("use_password_security", $CFG_GLPI["use_password_security"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_password_min_length$rand'>" . __('Password minimum length') . "</label></td>";
echo "<td>";
Dropdown::showNumber('password_min_length', ['value' => $CFG_GLPI["password_min_length"],
'min' => 4,
'max' => 30,
'rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_password_need_number$rand'>" . __('Password need digit') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("password_need_number", $CFG_GLPI["password_need_number"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_password_need_letter$rand'>" . __('Password need lowercase character') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("password_need_letter", $CFG_GLPI["password_need_letter"], -1, ['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_password_need_caps$rand'>" . __('Password need uppercase character') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("password_need_caps", $CFG_GLPI["password_need_caps"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='dropdown_password_need_symbol$rand'>" . __('Password need symbol') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("password_need_symbol", $CFG_GLPI["password_need_symbol"], -1, ['rand' => $rand]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4' class='center b'>".__('Maintenance mode');
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='dropdown_maintenance_mode$rand'>" . __('Maintenance mode') . "</label></td>";
echo "<td>";
Dropdown::showYesNo("maintenance_mode", $CFG_GLPI["maintenance_mode"], -1, ['rand' => $rand]);
echo "</td>";
echo "<td><label for='maintenance_text'>" . __('Maintenance text') . "</label></td>";
echo "<td>";
echo "<textarea cols='70' rows='4' name='maintenance_text' id='maintenance_text'>".$CFG_GLPI["maintenance_text"];
echo "</textarea>";
echo "</td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4' class='center b'>".__('Proxy configuration for upgrade check');
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='proxy_name'>" . __('Server') . "</label></td>";
echo "<td><input type='text' name='proxy_name' id='proxy_name' value='".$CFG_GLPI["proxy_name"]."'></td>";
echo "<td><label for='proxy_port'>" . __('Port') . "</label></td>";
echo "<td><input type='text' name='proxy_port' id='proxy_port' value='".$CFG_GLPI["proxy_port"]."'></td>";
echo "</tr>";
echo "<tr class='tab_bg_2'>";
echo "<td><label for='proxy_user'>" . __('Login') . "</label></td>";
echo "<td><input type='text' name='proxy_user' id='proxy_user' value='".$CFG_GLPI["proxy_user"]."'></td>";
echo "<td><label for='proxy_passwd'>" . __('Password') . "</label></td>";
echo "<td><input type='password' name='proxy_passwd' id='proxy_passwd' value='' autocomplete='off'>";
echo "<br><input type='checkbox' name='_blank_proxy_passwd' id='_blank_proxy_passwd'><label for='_blank_proxy_passwd'>".__('Clear')."</label>";
echo "</td></tr>";
echo "<tr class='tab_bg_2'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update' class='submit' value=\""._sx('button', 'Save')."\">";
echo "</td></tr>";
echo "</table>";
Html::closeForm();
$width = 128;
echo "<p>" . Telemetry::getViewLink() . "</p>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr><th>". __('Information about system installation and configuration')."</th></tr>";
echo "<tr class='tab_bg_1'><td>";
echo "<a class='vsubmit' href='?check_version'>".__('Check if a new version is available')."</a>";
echo "</td></tr>";
$oldlang = $_SESSION['glpilanguage'];
Session::loadLanguage('en_GB');
$ver = GLPI_VERSION;
if (is_dir(GLPI_ROOT."/.git")) {
$dir = getcwd();
chdir(GLPI_ROOT);
$returnCode = 1;
$gitrev = @exec('git show --format="%h" --no-patch 2>&1', $output, $returnCode);
$gitbranch = '';
if (!$returnCode) {
$gitbranch = @exec('git symbolic-ref --quiet --short HEAD || git rev-parse --short HEAD 2>&1', $output, $returnCode);
}
chdir($dir);
if (!$returnCode) {
$ver .= '-git-' .$gitbranch . '-' . $gitrev;
}
}
echo "<tr class='tab_bg_1'><td><pre>[code]\n \n";
echo "GLPI $ver (" . $CFG_GLPI['root_doc']." => " . GLPI_ROOT . ")\n";
echo "Installation mode: " . GLPI_INSTALL_MODE . "\n";
echo "\n</pre></td></tr>";
echo "<tr><th>Server</th></tr>\n";
echo "<tr class='tab_bg_1'><td><pre>\n \n";
echo wordwrap("Operating system: ".php_uname()."\n", $width, "\n\t");
$exts = get_loaded_extensions();
sort($exts);
echo wordwrap("PHP ".phpversion().' '.php_sapi_name()." (".implode(', ', $exts).")\n",
$width, "\n\t");
$msg = "Setup: ";
foreach (['max_execution_time', 'memory_limit', 'post_max_size', 'safe_mode',
'session.save_handler', 'upload_max_filesize'] as $key) {
$msg .= $key.'="'.ini_get($key).'" ';
}
echo wordwrap($msg."\n", $width, "\n\t");
$msg = 'Software: ';
if (isset($_SERVER["SERVER_SOFTWARE"])) {
$msg .= $_SERVER["SERVER_SOFTWARE"];
}
if (isset($_SERVER["SERVER_SIGNATURE"])) {
$msg .= ' ('.Html::clean($_SERVER["SERVER_SIGNATURE"]).')';
}
echo wordwrap($msg."\n", $width, "\n\t");
if (isset($_SERVER["HTTP_USER_AGENT"])) {
echo "\t" . Toolbox::clean_cross_side_scripting_deep($_SERVER["HTTP_USER_AGENT"]) . "\n";
}
foreach ($DB->getInfo() as $key => $val) {
echo "$key: $val\n\t";
}
echo "\n";
self::displayCheckExtensions(true);
self::displayCheckDbEngine(true);
self::checkWriteAccessToDirs(true);
toolbox::checkSELinux(true);
echo "\n</pre></td></tr>";
self::showLibrariesInformation();
foreach ($CFG_GLPI["systeminformations_types"] as $type) {
$tmp = new $type();
$tmp->showSystemInformations($width);
}
Session::loadLanguage($oldlang);
echo "<tr class='tab_bg_1'><td>[/code]\n</td></tr>";
echo "<tr class='tab_bg_2'><th>". __('To copy/paste in your support request')."</th></tr>\n";
echo "</table></div>\n";
}
static function getLibraryDir($libstring) {
if (is_object($libstring)) {
return realpath(dirname((new ReflectionObject($libstring))->getFileName()));
} else if (class_exists($libstring)) {
return realpath(dirname((new ReflectionClass($libstring))->getFileName()));
} else if (function_exists($libstring)) {
$path = (new ReflectionFunction($libstring))->getFileName();
return ($path ? realpath(dirname($path)) : false);
}
return false;
}
static function getLibraries($all = false) {
include_once(GLPI_HTMLAWED);
$pm = new PHPMailer();
$sp = new SimplePie();
$deps = [[ 'name' => 'htmLawed',
'version' => hl_version() ,
'check' => 'hl_version' ],
[ 'name' => 'phpmailer/phpmailer',
'version' => $pm::VERSION,
'check' => 'PHPMailer\\PHPMailer\\PHPMailer' ],
[ 'name' => 'simplepie/simplepie',
'version' => SIMPLEPIE_VERSION,
'check' => $sp ],
[ 'name' => 'tecnickcom/tcpdf',
'version' => TCPDF_STATIC::getTCPDFVersion(),
'check' => 'TCPDF' ],
[ 'name' => 'michelf/php-markdown',
'check' => 'Michelf\\Markdown' ],
[ 'name' => 'true/punycode',
'check' => 'TrueBV\\Punycode' ],
[ 'name' => 'iamcal/lib_autolink',
'check' => 'autolink' ],
[ 'name' => 'sabre/vobject',
'check' => 'Sabre\\VObject\\Component' ],
[ 'name' => 'zendframework/zend-cache',
'check' => 'Zend\\Cache\\Module' ],
[ 'name' => 'zendframework/zend-i18n',
'check' => 'Zend\\I18n\\Module' ],
[ 'name' => 'zendframework/zend-serializer',
'check' => 'Zend\\Serializer\\Module' ],
[ 'name' => 'monolog/monolog',
'check' => 'Monolog\\Logger' ],
[ 'name' => 'sebastian/diff',
'check' => 'SebastianBergmann\\Diff\\Diff' ],
[ 'name' => 'elvanto/litemoji',
'check' => 'LitEmoji\\LitEmoji' ],
[ 'name' => 'symfony/console',
'check' => 'Symfony\\Component\\Console\\Application' ],
[ 'name' => 'leafo/scssphp',
'check' => 'Leafo\ScssPhp\Compiler' ],
];
if ($all || PHP_VERSION_ID < 70000) {
$deps[] = [
'name' => 'paragonie/random_compat',
'check' => 'random_int'
];
}
if (Toolbox::canUseCAS()) {
$deps[] = [
'name' => 'phpCas',
'version' => phpCAS::getVersion(),
'check' => 'phpCAS'
];
}
return $deps;
}
static function showLibrariesInformation() {
echo "<tr class='tab_bg_2'><th>Libraries</th></tr>\n";
echo "<tr class='tab_bg_1'><td><pre>\n \n";
foreach (self::getLibraries() as $dep) {
$path = self::getLibraryDir($dep['check']);
if ($path) {
echo "{$dep['name']} ";
if (isset($dep['version'])) {
echo "version {$dep['version']} ";
}
echo "in ($path)\n";
} else {
echo "{$dep['name']} not found\n";
}
}
echo "\n</pre></td></tr>";
}
static function dropdownGlobalManagement($name, $value, $rand = null) {
$choices = [
__('Yes - Restrict to unit management for manual add'),
__('Yes - Restrict to global management for manual add'),
__('No'),
];
Dropdown::showFromArray($name, $choices, ['value'=>$value, 'rand' => $rand]);
}
static function getLanguage($lang) {
global $CFG_GLPI;
$altLang = str_replace("-", "_", $lang);
foreach ($CFG_GLPI["languages"] as $ID => $language) {
if ((strcasecmp($lang, $ID) == 0)
|| (strcasecmp($altLang, $ID) == 0)
|| (strcasecmp($lang, $language[2]) == 0)
|| (strcasecmp($lang, $language[3]) == 0)) {
return $ID;
}
}
foreach ($CFG_GLPI["languages"] as $ID => $language) {
if (strcasecmp($lang, $language[0]) == 0) {
return $ID;
}
}
foreach ($CFG_GLPI["languages"] as $ID => $language) {
if (strcasecmp($lang, $language[4]) == 0) {
return $ID;
}
}
return "";
}
static function detectRootDoc() {
global $CFG_GLPI;
if (!isset($CFG_GLPI["root_doc"])) {
if (!isset($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'];
}
$currentdir = getcwd();
chdir(GLPI_ROOT);
$glpidir = str_replace(str_replace('\\', '/', getcwd()), "",
str_replace('\\', '/', $currentdir));
chdir($currentdir);
$globaldir = Html::cleanParametersURL($_SERVER['REQUEST_URI']);
$globaldir = preg_replace("/\/[0-9a-zA-Z\.\-\_]+\.php/", "", $globaldir);
if (strpos($globaldir, 'api/') !== false) {
$globaldir = preg_replace("/(.*\/)api\/.*/", "$1", $globaldir);
}
$CFG_GLPI["root_doc"] = str_replace($glpidir, "", $globaldir);
$CFG_GLPI["root_doc"] = preg_replace("/\/$/", "", $CFG_GLPI["root_doc"]);
$CFG_GLPI["root_doc"] = urldecode($CFG_GLPI["root_doc"]);
}
}
function showDebug() {
$options = [
'diff' => 0,
'name' => '',
];
NotificationEvent::debugEvent(new DBConnection(), $options);
}
function showFormFieldUnicity() {
$unicity = new FieldUnicity();
$unicity->showForm(1, -1);
}
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
switch ($item->getType()) {
case 'Preference' :
return __('Personalization');
case 'User' :
if (User::canUpdate()
&& $item->currentUserHaveMoreRightThan($item->getID())) {
return __('Settings');
}
break;
case __CLASS__ :
$tabs = [
1 => __('General setup'),
2 => __('Default values'),
3 => __('Assets'),
4 => __('Assistance'),
];
if (Config::canUpdate()) {
$tabs[9] = __('Logs purge');
$tabs[5] = __('System');
$tabs[7] = __('Performance');
$tabs[8] = __('API');
}
if (DBConnection::isDBSlaveActive()
&& Config::canUpdate()) {
$tabs[6] = _n('SQL replica', 'SQL replicas', Session::getPluralNumber());
}
return $tabs;
}
return '';
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
global $CFG_GLPI;
if ($item->getType() == 'Preference') {
$config = new self();
$user = new User();
if ($user->getFromDB(Session::getLoginUserID())) {
$user->computePreferences();
$config->showFormUserPrefs($user->fields);
}
} else if ($item->getType() == 'User') {
$config = new self();
$item->computePreferences();
$config->showFormUserPrefs($item->fields);
} else if ($item->getType() == __CLASS__) {
switch ($tabnum) {
case 1 :
$item->showFormDisplay();
break;
case 2 :
$item->showFormUserPrefs($CFG_GLPI);
break;
case 3 :
$item->showFormInventory();
break;
case 4 :
$item->showFormHelpdesk();
break;
case 5 :
$item->showSystemInformations();
break;
case 6 :
$item->showFormDBSlave();
break;
case 7 :
$item->showPerformanceInformations();
break;
case 8 :
$item->showFormAPI();
break;
case 9:
$item->showFormLogs();
break;
}
}
return true;
}
static function displayCheckDbEngine($fordebug = false, $version = null) {
global $CFG_GLPI;
$error = 0;
$result = self::checkDbEngine($version);
$version = key($result);
$db_ver = $result[$version];
$ok_message = sprintf(__s('Database version seems correct (%s) - Perfect!'), $version);
$ko_message = sprintf(__s('Your database engine version seems too old: %s.'), $version);
if (!$db_ver) {
$error = 2;
}
$message = $error > 0 ? $ko_message : $ok_message;
$img = "<img src='".$CFG_GLPI['root_doc']."/pics/";
$img .= ($error > 0 ? "ko_min" : "ok_min") . ".png' alt='$message' title='$message'/>";
if (isCommandLine()) {
echo $message . "\n";
} else if ($fordebug) {
echo $img . $message . "\n";
} else {
$html = "<td";
if ($error > 0) {
$html .= " class='red'";
}
$html .= ">";
$html .= $img;
$html .= '</td>';
echo $html;
}
return $error;
}
static function displayCheckExtensions($fordebug = false) {
global $CFG_GLPI;
$report = self::checkExtensions();
foreach ($report['good'] as $ext => $msg) {
if (!$fordebug) {
echo "<tr class=\"tab_bg_1\"><td class=\"left b\">" . sprintf(__('%s extension test'), $ext) . "</td>";
echo "<td><img src=\"{$CFG_GLPI['root_doc']}/pics/ok_min.png\"
alt=\"$msg\"
title=\"$msg\"></td>";
echo "</tr>";
} else {
echo "<img src=\"{$CFG_GLPI['root_doc']}/pics/ok_min.png\"
alt=\"\">$msg\n";
}
}
foreach ($report['may'] as $ext => $msg) {
if (!$fordebug) {
echo "<tr class=\"tab_bg_1\"><td class=\"left b\">" . sprintf(__('%s extension test'), $ext) . "</td>";
echo "<td><img src=\"{$CFG_GLPI['root_doc']}/pics/warning_min.png\"> " . $msg . "</td>";
echo "</tr>";
} else {
echo "<img src=\"{$CFG_GLPI['root_doc']}/pics/warning_min.png\">" . $msg . "\n";
}
}
foreach ($report['missing'] as $ext => $msg) {
if (!$fordebug) {
echo "<tr class=\"tab_bg_1\"><td class=\"left b\">" . sprintf(__('%s extension test'), $ext) . "</td>";
echo "<td class=\"red\"><img src=\"{$CFG_GLPI['root_doc']}/pics/ko_min.png\"> " . $msg . "</td>";
echo "</tr>";
} else {
echo "<img src=\"{$CFG_GLPI['root_doc']}/pics/ko_min.png\">" . $msg . "\n";
}
}
return $report['error'];
}
static function checkDbEngine($raw = null) {
if ($raw === null) {
global $DB;
$raw = $DB->getVersion();
}
preg_match('/(\d+(\.)?)+/', $raw, $found);
$version = $found[0];
$db_ver = version_compare($version, '5.6', '>=');
return [$version => $db_ver];
}
static function checkExtensions($list = null) {
if ($list === null) {
$extensions_to_check = [
'mysqli' => [
'required' => true
],
'ctype' => [
'required' => true,
'function' => 'ctype_digit',
],
'fileinfo' => [
'required' => true,
'class' => 'finfo'
],
'json' => [
'required' => true,
'function' => 'json_encode'
],
'mbstring' => [
'required' => true,
],
'iconv' => [
'required' => true,
],
'zlib' => [
'required' => true,
],
'curl' => [
'required' => true,
],
'gd' => [
'required' => true,
],
'simplexml' => [
'required' => true,
],
'xml' => [
'required' => true,
'function' => 'utf8_decode'
],
'ldap' => [
'required' => false,
],
'imap' => [
'required' => false,
],
'Zend OPcache' => [
'required' => false
],
'APCu' => [
'required' => false,
'function' => 'apcu_fetch'
],
'xmlrpc' => [
'required' => false
],
'CAS' => [
'required' => false,
'class' => 'phpCAS'
],
'exif' => [
'required' => false
]
];
} else {
$extensions_to_check = $list;
}
$report = [
'error' => 0,
'good' => [],
'missing' => [],
'may' => []
];
foreach ($extensions_to_check as $ext => $params) {
$success = true;
if (isset($params['call'])) {
$success = call_user_func($params['call']);
} else if (isset($params['function'])) {
if (!function_exists($params['function'])) {
$success = false;
}
} else if (isset($params['class'])) {
if (!class_exists($params['class'])) {
$success = false;
}
} else {
if (!extension_loaded($ext)) {
$success = false;
}
}
if ($success) {
$msg = sprintf(__('%s extension is installed'), $ext);
$report['good'][$ext] = $msg;
} else {
if (isset($params['required']) && $params['required'] === true) {
if ($report['error'] < 2) {
$report['error'] = 2;
}
$msg = sprintf(__('%s extension is missing'), $ext);
$report['missing'][$ext] = $msg;
} else {
if ($report['error'] < 1) {
$report['error'] = 1;
}
$msg = sprintf(__('%s extension is not present'), $ext);
$report['may'][$ext] = $msg;
}
}
}
return $report;
}
private static function getDataDirectories() {
$dir_to_check = [
GLPI_CONFIG_DIR => __('Checking write permissions for setting files'),
GLPI_DOC_DIR => __('Checking write permissions for document files'),
GLPI_DUMP_DIR => __('Checking write permissions for dump files'),
GLPI_SESSION_DIR => __('Checking write permissions for session files'),
GLPI_CRON_DIR => __('Checking write permissions for automatic actions files'),
GLPI_GRAPH_DIR => __('Checking write permissions for graphic files'),
GLPI_LOCK_DIR => __('Checking write permissions for lock files'),
GLPI_PLUGIN_DOC_DIR => __('Checking write permissions for plugins document files'),
GLPI_TMP_DIR => __('Checking write permissions for temporary files'),
GLPI_CACHE_DIR => __('Checking write permissions for cache files'),
GLPI_RSS_DIR => __('Checking write permissions for rss files'),
GLPI_UPLOAD_DIR => __('Checking write permissions for upload files'),
GLPI_PICTURE_DIR => __('Checking write permissions for pictures files')
];
return $dir_to_check;
}
static function checkWriteAccessToDirs($fordebug = false) {
global $CFG_GLPI;
if (!$fordebug) {
echo "<tr class='tab_bg_1'><td class='b left'>".
__('Checking write permissions for log files')."</td>";
}
$can_write_logs = false;
try {
global $PHPLOGGER;
$PHPLOGGER->addRecord(Monolog\Logger::WARNING, "Test logger");
$can_write_logs = true;
} catch (\UnexpectedValueException $e) {
$catched = true;
}
if ($can_write_logs) {
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".__s('OK')."\">".
GLPI_LOG_DIR." : OK\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".
__s('A file was created - Perfect!')."\" title=\"".
__s('A file was created - Perfect!')."\"></td></tr>";
}
} else {
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".
sprintf(__('Check permissions to the directory: %s'), GLPI_LOG_DIR)."\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".
"<p class='red'>".__('The file could not be created.')."</p>".
sprintf(__('Check permissions to the directory: %s'), GLPI_LOG_DIR)."</td></tr>";
}
}
if ($can_write_logs) {
$dir_to_check = self::getDataDirectories();
unset($dir_to_check[GLPI_LOG_DIR]);
$error = 0;
foreach ($dir_to_check as $dir => $message) {
if (!$fordebug) {
echo "<tr class='tab_bg_1'><td class='left b'>".$message."</td>";
}
$tmperror = Toolbox::testWriteAccessToDirectory($dir);
$errors = [
4 => __('The directory could not be created.'),
3 => __('The directory was created but could not be removed.'),
2 => __('The file could not be created.'),
1 => __("The file was created but can't be deleted.")
];
if ($tmperror > 0) {
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/ko_min.png'> ".
sprintf(__('Check permissions to the directory: %s'), $dir).
" ".$errors[$tmperror]."\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/ko_min.png'><p class='red'>".
$errors[$tmperror]."</p> ".
sprintf(__('Check permissions to the directory: %s'), $dir).
"'</td></tr>";
}
$error = 2;
} else {
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".__s('OK').
"\">$dir : OK\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".
__s('A file and a directory have be created and deleted - Perfect!')."\"
title=\"".
__s('A file and a directory have be created and deleted - Perfect!')."\">".
"</td></tr>";
}
}
}
} else {
$error = 2;
}
$check_access = false;
$directories = array_keys(self::getDataDirectories());
foreach ($directories as $dir) {
if (Toolbox::startsWith($dir, GLPI_ROOT)) {
$check_access = true;
break;
}
}
if ($check_access) {
$oldhand = set_error_handler(function($errno, $errmsg, $filename, $linenum, $vars){return true;});
$oldlevel = error_reporting(0);
$context = stream_context_create([
'http' => [
'timeout' => 2.0
]
]);
$protocol = 'http';
if (isset($_SERVER['HTTPS'])) {
$protocol = 'https';
}
$uri = $protocol . '://' . $_SERVER['SERVER_NAME'] . $CFG_GLPI['root_doc'];
if ($fic = fopen($uri.'/index.php?skipCheckWriteAccessToDirs=1', 'r', false, $context)) {
fclose($fic);
if (!$fordebug) {
echo "<tr class='tab_bg_1'><td class='b left'>".
__('Web access to files directory is protected')."</td>";
}
if ($fic = fopen($uri.'/files/_log/php-errors.log', 'r', false, $context)) {
fclose($fic);
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".
__('Web access to the files directory should not be allowed')."\n".
__('Check the .htaccess file and the web server configuration.')."\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".
"<p class='red'>".__('Web access to the files directory should not be allowed')."<br/>".
__('Check the .htaccess file and the web server configuration.')."</p></td></tr>";
}
$error = 1;
} else {
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".
__s('Web access to files directory is protected')."\">".
__s('Web access to files directory is protected')." : OK\n";
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/ok_min.png' alt=\"".
__s('Web access to files directory is protected')."\" title=\"".
__s('Web access to files directory is protected')."\"></td></tr>";
}
}
} else {
$msg = __('Web access to the files directory should not be allowed but this cannot be checked automatically on this instance.')."\n".
"Make sure acces to <a href='{$CFG_GLPI['root_doc']}/files/_log/php-errors.log'>".__('error log file')."</a> is forbidden; otherwise review .htaccess file and web server configuration.";
if ($fordebug) {
echo "<img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".$msg;
} else {
echo "<td><img src='".$CFG_GLPI['root_doc']."/pics/warning_min.png'>".
"<p class='red'>".nl2br($msg)."</p></td></tr>";
}
}
error_reporting($oldlevel);
set_error_handler($oldhand);
}
return $error;
}
static function getCurrentDBVersion() {
global $DB;
$select = 'value AS version';
$table = 'glpi_configs';
$where = [
'context' => 'core',
'name' => 'version'
];
if (!$DB->tableExists('glpi_configs')) {
$select = 'version';
$table = 'glpi_config';
$where = ['id' => 1];
} else if ($DB->fieldExists('glpi_configs', 'version')) {
$select = 'version';
$where = ['id' => 1];
}
$row = $DB->request([
'SELECT' => [$select],
'FROM' => $table,
'WHERE' => $where
])->next();
return trim($row['version']);
}
static function getConfigurationValues($context, array $names = []) {
global $DB;
$query = [
'FROM' => self::getTable(),
'WHERE' => [
'context' => $context
]
];
if (count($names) > 0) {
$query['WHERE']['name'] = $names;
}
$iterator = $DB->request($query);
$result = [];
while ($line = $iterator->next()) {
$result[$line['name']] = $line['value'];
}
return $result;
}
public static function loadLegacyConfiguration($older_to_latest = true) {
global $CFG_GLPI, $DB;
$config_tables_iterator = $DB->listTables('glpi_config%');
$config_tables = [];
foreach ($config_tables_iterator as $config_table) {
$config_tables[] = $config_table['TABLE_NAME'];
}
$get_prior_to_078_config = function() use ($DB, $config_tables) {
if (!in_array('glpi_config', $config_tables)) {
return false;
}
$config = new Config();
$config->forceTable('glpi_config');
if ($config->getFromDB(1)) {
return $config->fields;
}
return false;
};
$get_078_to_latest_config = function() use ($DB, $config_tables) {
if (!in_array('glpi_configs', $config_tables)) {
return false;
}
Config::forceTable('glpi_configs');
$iterator = $DB->request(['FROM' => 'glpi_configs']);
if ($iterator->count() === 0) {
return false;
}
if ($iterator->count() === 1) {
return $iterator->next();
}
$config = [];
while ($row = $iterator->next()) {
if ('core' !== $row['context']) {
continue;
}
$config[$row['name']] = $row['value'];
}
return $config;
};
$functions = [];
if ($older_to_latest) {
$functions = [
$get_prior_to_078_config,
$get_078_to_latest_config,
];
} else {
$functions = [
$get_078_to_latest_config,
$get_prior_to_078_config,
];
}
$values = [];
foreach ($functions as $function) {
if ($config = $function()) {
$values = $config;
break;
}
}
if (count($values) === 0) {
return false;
}
$CFG_GLPI = array_merge($CFG_GLPI, $values);
if (isset($CFG_GLPI['priority_matrix'])) {
$CFG_GLPI['priority_matrix'] = importArrayFromDB($CFG_GLPI['priority_matrix']);
}
if (isset($CFG_GLPI['lock_item_list'])) {
$CFG_GLPI['lock_item_list'] = importArrayFromDB($CFG_GLPI['lock_item_list']);
}
if (isset($CFG_GLPI['lock_lockprofile_id'])
&& $CFG_GLPI['lock_use_lock_item']
&& $CFG_GLPI['lock_lockprofile_id'] > 0
&& !isset($CFG_GLPI['lock_lockprofile'])) {
$prof = new Profile();
$prof->getFromDB($CFG_GLPI['lock_lockprofile_id']);
$prof->cleanProfile();
$CFG_GLPI['lock_lockprofile'] = $prof->fields;
}
if (isset($CFG_GLPI['root_doc'])) {
$CFG_GLPI['typedoc_icon_dir'] = $CFG_GLPI['root_doc'] . '/pics/icones';
}
return true;
}
static function setConfigurationValues($context, array $values = []) {
$config = new self();
foreach ($values as $name => $value) {
if ($config->getFromDBByCrit([
'context' => $context,
'name' => $name
])) {
$input = ['id' => $config->getID(),
'context' => $context,
'value' => $value];
$config->update($input);
} else {
$input = ['context' => $context,
'name' => $name,
'value' => $value];
$config->add($input);
}
}
}
static function deleteConfigurationValues($context, array $values = []) {
$config = new self();
foreach ($values as $value) {
if ($config->getFromDBByCrit([
'context' => $context,
'name' => $value
])) {
$config->delete(['id' => $config->getID()]);
}
}
}
function getRights($interface = 'central') {
$values = parent::getRights();
unset($values[CREATE], $values[DELETE],
$values[PURGE]);
return $values;
}
public static function agreeDevMessage($bg = false) {
$msg = '<p class="'.($bg ? 'mig' : '') .'red"><strong>' . __('You are using a development version, be careful!') . '</strong><br/>';
$msg .= "<input type='checkbox' required='required' id='agree_dev' name='agree_dev'/><label for='agree_dev'>" . __('I know I am using a unstable version.') . "</label></p>";
$msg .= "<script type=text/javascript>
$(function() {
$('[name=from_update]').on('click', function(event){
if(!$('#agree_dev').is(':checked')) {
event.preventDefault();
alert('" . __('Please check the unstable version checkbox.') . "');
}
});
});
</script>";
return $msg;
}
public static function getCache($optname, $context = 'core', $psr16 = true) {
global $DB;
$conf = [];
if ($DB
&& $DB->connected
&& $DB->fieldExists(self::getTable(), 'context')
) {
$conf = self::getConfigurationValues($context, [$optname]);
}
$opt = [];
if (isset($conf[$optname])) {
$opt = json_decode($conf[$optname], true);
Toolbox::logDebug("CACHE CONFIG $optname", $opt);
}
if (defined('TU_USER') && !defined('CACHED_TESTS')) {
$opt['adapter'] = 'memory';
}
if (defined('TU_USER') && $optname == 'cache_trans') {
$opt['adapter'] = 'filesystem';
}
if (!isset($opt['options']['namespace'])) {
$namespace = "glpi_${optname}_" . GLPI_VERSION;
if ($DB) {
$namespace .= md5(
(is_array($DB->dbhost) ? implode(' ', $DB->dbhost) : $DB->dbhost) . $DB->dbdefault
);
}
$opt['options']['namespace'] = $namespace;
}
if (!isset($opt['adapter'])) {
if (function_exists('apcu_fetch')) {
$opt['adapter'] = (version_compare(PHP_VERSION, '7.0.0') >= 0) ? 'apcu' : 'apc';
} else if (function_exists('wincache_ucache_add')) {
$opt['adapter'] = 'wincache';
} else {
$opt['adapter'] = 'filesystem';
}
$skip_integrity_checks = false;
$is_computed_config = true;
} else {
$opt['adapter'] = strtolower($opt['adapter']);
switch ($opt['adapter']) {
case 'dba':
case 'ext_mongo_db':
case 'extmongodb':
case 'filesystem':
case 'memcache':
case 'memcached':
case 'mongo_db':
case 'mongodb':
case 'redis':
$skip_integrity_checks = true;
break;
case 'apc':
case 'apcu':
case 'memory':
case 'session':
case 'win_cache':
case 'wincache':
case 'zend_server_disk':
case 'zendserverdisk':
case 'zend_server_shm':
case 'zendservershm':
default:
$skip_integrity_checks = false;
break;
}
$is_computed_config = false;
}
$ser = false;
switch ($opt['adapter']) {
case 'filesystem':
if (!isset($opt['options']['cache_dir'])) {
$opt['options']['cache_dir'] = $optname;
}
$opt['options']['cache_dir'] = GLPI_CACHE_DIR . '/' . $opt['options']['cache_dir'];
if (!is_dir($opt['options']['cache_dir'])) {
mkdir($opt['options']['cache_dir']);
}
$ser = true;
break;
case 'dba':
if (!isset($opt['options']['pathname'])) {
$opt['options']['pathname'] = "$optname.data";
}
$opt['options']['pathname'] = GLPI_CACHE_DIR . '/' . $opt['options']['pathname'];
$ser = true;
break;
case 'redis':
$ser = true;
break;
}
if ($ser && !isset($opt['plugins'])) {
$opt['plugins'] = ['serializer'];
}
try {
$storage = Zend\Cache\StorageFactory::factory($opt);
} catch (Exception $e) {
if (!$is_computed_config) {
Toolbox::logError($e->getMessage());
}
$fallback = false;
if ($is_computed_config && $opt['adapter'] != 'filesystem') {
$opt = [
'adapter' => 'filesystem',
'options' => [
'cache_dir' => GLPI_CACHE_DIR . '/' . $optname,
'namespace' => $namespace,
],
'plugins' => ['serializer']
];
if (!is_dir($opt['options']['cache_dir'])) {
mkdir($opt['options']['cache_dir']);
}
try {
$storage = Zend\Cache\StorageFactory::factory($opt);
$fallback = true;
} catch (Exception $e1) {
Toolbox::logError($e1->getMessage());
if (isset($_SESSION['glpi_use_mode'])
&& Session::DEBUG_MODE == $_SESSION['glpi_use_mode']) {
Toolbox::logDebug($e->getMessage());
}
}
}
if ($fallback === false) {
$opt = ['adapter' => 'memory'];
$storage = Zend\Cache\StorageFactory::factory($opt);
}
if (isset($_SESSION['glpi_use_mode'])
&& Session::DEBUG_MODE == $_SESSION['glpi_use_mode']) {
Toolbox::logDebug($e->getMessage());
}
}
if (defined('TU_USER')) {
$skip_integrity_checks = true;
}
if ($psr16) {
return new SimpleCache($storage, GLPI_CACHE_DIR, !$skip_integrity_checks);
} else {
return $storage;
}
}
public function getPalettes() {
$themes_files = scandir(GLPI_ROOT."/css/palettes/");
$themes = [];
foreach ($themes_files as $file) {
if (strpos($file, ".scss") !== false) {
$name = substr($file, 1, -5);
$themes[$name] = ucfirst($name);
}
}
return $themes;
}
function showFormLogs() {
global $CFG_GLPI;
if (!Config::canUpdate()) {
return false;
}
echo "<form name='form' id='purgelogs_form' method='post' action='".$this->getFormURL()."'>";
echo "<div class='center'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr class='tab_bg_1'><th colspan='4'>".__("Logs purge configuration").
"</th></tr>";
echo "<tr class='tab_bg_1 center'><td colspan='4'><i>".__("Change all")."</i>";
echo Html::scriptBlock("function form_init_all(value) {
$('#purgelogs_form .purgelog_interval select').val(value).trigger('change');;
}");
self::showLogsInterval(
'init_all',
0,
[
'on_change' => "form_init_all(this.value);",
'class' => ''
]
);
echo "</td></tr>";
echo "<input type='hidden' name='id' value='1'>";
echo "<tr class='tab_bg_1'><th colspan='4'>".__("General")."</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Add/update relation between items").
"</td><td>";
self::showLogsInterval('purge_addrelation', $CFG_GLPI["purge_addrelation"]);
echo "</td>";
echo "<td>".__("Delete relation between items")."</td><td>";
self::showLogsInterval('purge_deleterelation', $CFG_GLPI["purge_deleterelation"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Add the item")."</td><td>";
self::showLogsInterval('purge_createitem', $CFG_GLPI["purge_createitem"]);
echo "</td>";
echo "<td>".__("Delete the item")."</td><td>";
self::showLogsInterval('purge_deleteitem', $CFG_GLPI["purge_deleteitem"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Restore the item")."</td><td>";
self::showLogsInterval('purge_restoreitem', $CFG_GLPI["purge_restoreitem"]);
echo "</td>";
echo "<td>".__('Update the item')."</td><td>";
self::showLogsInterval('purge_updateitem', $CFG_GLPI["purge_updateitem"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Comments")."</td><td>";
self::showLogsInterval('purge_comments', $CFG_GLPI["purge_comments"]);
echo "</td>";
echo "<td>".__("Last update")."</td><td>";
self::showLogsInterval('purge_datemod', $CFG_GLPI["purge_datemod"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("Plugins")."</td><td>";
self::showLogsInterval('purge_plugins', $CFG_GLPI["purge_plugins"]);
echo "</td>";
echo "<td class='center'></td><td>";
echo "</td></tr>";
echo "<tr class='tab_bg_1'><th colspan='4'>"._n('Software', 'Software', 2)."</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("Installation/uninstallation of software on computers")."</td><td>";
self::showLogsInterval('purge_computer_software_install',
$CFG_GLPI["purge_computer_software_install"]);
echo "</td>";
echo "<td>".__("Installation/uninstallation versions on softwares")."</td><td>";
self::showLogsInterval('purge_software_version_install',
$CFG_GLPI["purge_software_version_install"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("Add/Remove computers from software versions")."</td><td>";
self::showLogsInterval('purge_software_computer_install',
$CFG_GLPI["purge_software_computer_install"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><th colspan='4'>".__('Financial and administrative information').
"</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("Add financial information to an item")."</td><td>";
self::showLogsInterval('purge_infocom_creation', $CFG_GLPI["purge_infocom_creation"]);
echo "</td>";
echo "<td colspan='2'></td></tr>";
echo "<tr class='tab_bg_1'><th colspan='4'>"._n('User', 'Users', 2)."</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("Add/remove profiles to users")."</td><td>";
self::showLogsInterval('purge_profile_user', $CFG_GLPI["purge_profile_user"]);
echo "</td>";
echo "<td>".__("Add/remove groups to users")."</td><td>";
self::showLogsInterval('purge_group_user', $CFG_GLPI["purge_group_user"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".
__("User authentication method changes")."</td><td>";
self::showLogsInterval('purge_user_auth_changes', $CFG_GLPI["purge_user_auth_changes"]);
echo "</td>";
echo "<td class='center'>".__("Deleted user in LDAP directory").
"</td><td>";
self::showLogsInterval('purge_userdeletedfromldap', $CFG_GLPI["purge_userdeletedfromldap"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><th colspan='4'>"._n('Component', 'Components', 2)."</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Add component")."</td><td>";
self::showLogsInterval('purge_adddevice', $CFG_GLPI["purge_adddevice"]);
echo "</td>";
echo "<td>".__("Update component")."</td><td>";
self::showLogsInterval('purge_updatedevice', $CFG_GLPI["purge_updatedevice"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Disconnect a component").
"</td><td>";
self::showLogsInterval('purge_disconnectdevice', $CFG_GLPI["purge_disconnectdevice"]);
echo "</td>";
echo "<td>".__("Connect a component")."</td><td>";
self::showLogsInterval('purge_connectdevice', $CFG_GLPI["purge_connectdevice"]);
echo "</td>";
echo "</tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Delete component").
"</td><td>";
self::showLogsInterval('purge_deletedevice', $CFG_GLPI["purge_deletedevice"]);
echo "</td>";
echo "<td colspan='2'></td></tr>";
echo "<tr class='tab_bg_1'><th colspan='4'>".__("All sections")."</th></tr>";
echo "<tr class='tab_bg_1'><td class='center'>".__("Purge all log entries")."</td><td>";
self::showLogsInterval('purge_all', $CFG_GLPI["purge_all"]);
echo "</td>";
echo "<td colspan='2'></td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4' class='center'>";
echo "<input type='submit' name='update' value=\""._sx('button', 'Save')."\" class='submit' >";
echo"</td>";
echo "</tr>";
echo "</table></div>";
Html::closeForm();
}
static function showLogsInterval($name, $value, $options = []) {
$values = [
self::DELETE_ALL => __("Delete all"),
self::KEEP_ALL => __("Keep all"),
];
for ($i = 1; $i < 121; $i++) {
$values[$i] = sprintf(
_n(
"Delete if older than %s month",
"Delete if older than %s months",
$i
),
$i
);
}
$options = array_merge([
'value' => $value,
'display' => false,
'class' => 'purgelog_interval'
], $options);
$out = "<div class='{$options['class']}'>";
$out.= Dropdown::showFromArray($name, $values, $options);
$out.= "</div>";
echo $out;
}
public function rawSearchOptions() {
$tab = [];
$tab[] = [
'id' => 'common',
'name' => __('Characteristics')
];
$tab[] = [
'id' => 1,
'table' => $this->getTable(),
'field' => 'value',
'name' => __('Value'),
'massiveaction' => false
];
return $tab;
}
function getLogTypeID() {
return [$this->getType(), 1];
}
public function post_updateItem($history = 1) {
if (count($this->oldvalues)) {
foreach ($this->oldvalues as &$value) {
$value = $this->fields['name'] . ' ' . $value;
}
Log::constructHistory($this, $this->oldvalues, $this->fields);
}
}
}