暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

function.php 121KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519
  1. <?php
  2. /**
  3. * 易优CMS
  4. * ============================================================================
  5. * 版权所有 2016-2028 海南赞赞网络科技有限公司,并保留所有权利。
  6. * 网站地址: http://www.eyoucms.com
  7. * ----------------------------------------------------------------------------
  8. * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
  9. * ============================================================================
  10. * Author: 小虎哥 <1105415366@qq.com>
  11. * Date: 2018-4-3
  12. */
  13. if (!function_exists('unifyPriceHandle')) {
  14. /**
  15. * 显示价格统一处理
  16. * @param string $price 金额
  17. * @param bool $decimal 是否保留小数,true保留,false不保留
  18. * @return string
  19. */
  20. function unifyPriceHandle($price = 0, $decimal = false)
  21. {
  22. // 为空则返回 0
  23. if (empty($price)) return 0;
  24. // 保留两位小数
  25. $price = sprintf("%.2f", $price);
  26. // 不保留小数,强制转换浮点类型
  27. if (empty($decimal)) $price = floatval($price);
  28. // 返回结果
  29. return $price;
  30. }
  31. }
  32. if (!function_exists('convert_arr_key')) {
  33. /**
  34. * 将数据库中查出的列表以指定的 id 作为数组的键名
  35. *
  36. * @param array $arr 数组
  37. * @param string $key_name 数组键名
  38. * @return array
  39. */
  40. function convert_arr_key($arr, $key_name)
  41. {
  42. if (function_exists('array_column')) {
  43. return array_column($arr, null, $key_name);
  44. }
  45. $arr2 = array();
  46. foreach ($arr as $key => $val) {
  47. $arr2[$val[$key_name]] = $val;
  48. }
  49. return $arr2;
  50. }
  51. }
  52. if (!function_exists('reform_keys')) {
  53. /**
  54. * 重置数组索引,兼容多维数组
  55. *
  56. * @param array $arr 数组
  57. * @param string $key_name 数组键名
  58. * @return array
  59. */
  60. function reform_keys($array){
  61. if(!is_array($array)){
  62. return $array;
  63. }
  64. $keys = implode('', array_keys($array));
  65. if(is_numeric($keys)){
  66. $array = array_values($array);
  67. }
  68. $array = array_map('reform_keys', $array);
  69. return $array;
  70. }
  71. }
  72. if (!function_exists('func_encrypt')) {
  73. /**
  74. * md5加密
  75. *
  76. * @param string $str 字符串
  77. * @return array
  78. */
  79. function func_encrypt($pwd, $is_admin = false, $type = 'bcrypt')
  80. {
  81. $pwd = trim($pwd);
  82. $auth_code = get_auth_code($type);
  83. if ('bcrypt' == $type) {
  84. $encry_pwd = crypt($pwd, $auth_code);
  85. } else {
  86. $encry_pwd = md5($auth_code . $pwd);
  87. }
  88. return $encry_pwd;
  89. }
  90. }
  91. if (!function_exists('pwd_encry_type'))
  92. {
  93. /**
  94. * 获取密码加密方式
  95. * @param string $encry_pwd
  96. * @return [type] [description]
  97. */
  98. function pwd_encry_type($encry_pwd = '') {
  99. $entry = 'md5';
  100. if (32 != strlen($encry_pwd)) {
  101. if (defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH == 1) {
  102. $entry = 'bcrypt';
  103. }
  104. }
  105. return $entry;
  106. }
  107. }
  108. if (!function_exists('get_auth_code')) {
  109. /**
  110. * 密码加密盐值
  111. */
  112. function get_auth_code($type = 'bcrypt')
  113. {
  114. $auth_code = '';
  115. if ($type == 'bcrypt') { // crypt加密方式
  116. $lang = get_current_lang(true);
  117. $auth_code = \think\Db::name('config')->where(['name'=>'system_crypt_auth_code','inc_type'=>'system','lang'=>$lang])->value('value');
  118. if (empty($auth_code)) {
  119. $rand_str = md5(uniqid(rand(), true));
  120. $rand_str = substr($rand_str, 0, 23);
  121. $auth_code = '$2y$11$'.$rand_str; //30位盐
  122. /*多语言*/
  123. if (is_language()) {
  124. $langRow = \think\Db::name('language')->order('id asc')->select();
  125. foreach ($langRow as $key => $val) {
  126. tpCache('system', ['system_crypt_auth_code' => $auth_code], $val['mark']);
  127. }
  128. } else { // 单语言
  129. tpCache('system', ['system_crypt_auth_code' => $auth_code]);
  130. }
  131. /*--end*/
  132. }
  133. } else { // md5加密方式
  134. $lang = get_current_lang(true);
  135. $auth_code = \think\Db::name('config')->where(['name'=>'system_auth_code','inc_type'=>'system','lang'=>$lang])->value('value');
  136. if (empty($auth_code)) {
  137. $auth_code = \think\Config::get('AUTH_CODE');
  138. /*多语言*/
  139. if (is_language()) {
  140. $langRow = \think\Db::name('language')->order('id asc')->select();
  141. foreach ($langRow as $key => $val) {
  142. tpCache('system', ['system_auth_code' => $auth_code], $val['mark']);
  143. }
  144. } else { // 单语言
  145. tpCache('system', ['system_auth_code' => $auth_code]);
  146. }
  147. /*--end*/
  148. }
  149. }
  150. return $auth_code;
  151. }
  152. }
  153. if (!function_exists('get_arr_column')) {
  154. /**
  155. * 获取数组中的某一列
  156. *
  157. * @param array $arr 数组
  158. * @param string $key_name 列名
  159. * @return array 返回那一列的数组
  160. */
  161. function get_arr_column($arr, $key_name)
  162. {
  163. if (function_exists('array_column')) {
  164. return array_column($arr, $key_name);
  165. }
  166. $arr2 = array();
  167. foreach ($arr as $key => $val) {
  168. $arr2[] = $val[$key_name];
  169. }
  170. return $arr2;
  171. }
  172. }
  173. if (!function_exists('parse_url_param')) {
  174. /**
  175. * 获取url 中的各个参数 类似于 pay_code=alipay&bank_code=ICBC-DEBIT
  176. * @param string $url
  177. * @return type
  178. */
  179. function parse_url_param($url = '')
  180. {
  181. $url = rtrim($url, '/');
  182. $data = array();
  183. $str = explode('?', $url);
  184. $str = end($str);
  185. $parameter = explode('&', $str);
  186. foreach ($parameter as $val) {
  187. if (!empty($val)) {
  188. $tmp = explode('=', $val);
  189. $data[$tmp[0]] = $tmp[1];
  190. }
  191. }
  192. return $data;
  193. }
  194. }
  195. if (!function_exists('getClientIP')) {
  196. /**
  197. * 客户端IP(新)
  198. */
  199. function getClientIP()
  200. {
  201. if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
  202. $ip = getenv('HTTP_CLIENT_IP');
  203. } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
  204. $ip = getenv('HTTP_X_FORWARDED_FOR');
  205. } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
  206. $ip = getenv('REMOTE_ADDR');
  207. } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
  208. $ip = $_SERVER['REMOTE_ADDR'];
  209. }
  210. return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches [0] : '';
  211. }
  212. }
  213. if (!function_exists('clientIP')) {
  214. /**
  215. * 客户端IP(旧,目前存在未知异常,获取的IP有不准的情况)
  216. */
  217. function clientIP()
  218. {
  219. $ip = request()->ip();
  220. if (preg_match('/^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1 -9]?\d))))$/', $ip))
  221. return $ip;
  222. else
  223. return '';
  224. }
  225. }
  226. if (!function_exists('serverIP')) {
  227. /**
  228. * 服务器端IP
  229. */
  230. function serverIP()
  231. {
  232. // 会因为解析问题导致后台卡
  233. if (!empty($_SERVER['SERVER_ADDR']) && !preg_match('/127\.0\.\d{1,3}\.\d{1,3}/i', $_SERVER['SERVER_ADDR']) && !preg_match('/192\.168\.\d{1,3}\.\d{1,3}/i', $_SERVER['SERVER_ADDR'])) {
  234. $serviceIp = $_SERVER['SERVER_ADDR'];
  235. } else {
  236. $serviceIp = @gethostbyname($_SERVER["SERVER_NAME"]);
  237. }
  238. return $serviceIp;
  239. }
  240. }
  241. if (!function_exists('recurse_copy')) {
  242. /**
  243. * 自定义函数递归的复制带有多级子目录的目录
  244. * 递归复制文件夹
  245. *
  246. * @param type $src 原目录
  247. * @param type $dst 复制到的目录
  248. */
  249. //参数说明:
  250. //自定义函数递归的复制带有多级子目录的目录
  251. function recurse_copy($src, $dst)
  252. {
  253. $now = getTime();
  254. $dir = opendir($src);
  255. @mkdir($dst);
  256. if ('Weapp' == CONTROLLER_NAME && stristr(ACTION_NAME, 'install') && !is_writeable(ROOT_PATH.'weapp')) {
  257. return '请检查以下网站目录权限是否可写<br/>(application|template|weapp)';
  258. }
  259. while (false !== $file = readdir($dir)) {
  260. if (($file != '.') && ($file != '..')) {
  261. if (is_dir($src . '/' . $file)) {
  262. recurse_copy($src . '/' . $file, $dst . '/' . $file);
  263. } else {
  264. if (file_exists($dst . DIRECTORY_SEPARATOR . $file)) {
  265. if (!is_writeable($dst . DIRECTORY_SEPARATOR . $file)) {
  266. // exit($dst . DIRECTORY_SEPARATOR . $file . '不可写');
  267. return '网站目录没有写入权限,请调整权限';
  268. }
  269. // @unlink($dst . DIRECTORY_SEPARATOR . $file);
  270. }
  271. // if (file_exists($dst . DIRECTORY_SEPARATOR . $file)) {
  272. // @unlink($dst . DIRECTORY_SEPARATOR . $file);
  273. // }
  274. $copyrt = @copy($src . DIRECTORY_SEPARATOR . $file, $dst . DIRECTORY_SEPARATOR . $file);
  275. if (!$copyrt) {
  276. // echo 'copy ' . $dst . DIRECTORY_SEPARATOR . $file . ' failed';
  277. return '网站目录没有写入权限,请调整权限';
  278. }
  279. }
  280. }
  281. }
  282. closedir($dir);
  283. return true;
  284. }
  285. }
  286. if (!function_exists('delFile')) {
  287. /**
  288. * 递归删除文件夹
  289. *
  290. * @param string $path 目录路径
  291. * @param boolean $delDir 是否删除空目录
  292. * @return boolean
  293. */
  294. function delFile($path, $delDir = FALSE)
  295. {
  296. if (preg_match('/^(.+)\/$/i', $path)) {
  297. $path = rtrim($path, '/');
  298. }
  299. if (!is_dir($path)) {return FALSE;}
  300. $handle = @opendir($path);
  301. if ($handle) {
  302. while (false !== ($item = readdir($handle))) {
  303. if ($item != "." && $item != "..")
  304. is_dir("$path/$item") ? delFile("$path/$item", $delDir) : @unlink("$path/$item");
  305. }
  306. closedir($handle);
  307. if ($delDir) {
  308. return @rmdir($path);
  309. }
  310. } else {
  311. if (file_exists($path)) {
  312. return @unlink($path);
  313. } else {
  314. return FALSE;
  315. }
  316. }
  317. }
  318. }
  319. if (!function_exists('getDirFile')) {
  320. /**
  321. * 递归读取文件夹文件
  322. *
  323. * @param string $directory 目录路径
  324. * @param string $dir_name 显示的目录前缀路径
  325. * @param array $arr_file 是否删除空目录
  326. * @return boolean
  327. */
  328. function getDirFile($directory, $dir_name = '', &$arr_file = array())
  329. {
  330. if (!file_exists($directory)) {
  331. return false;
  332. }
  333. $mydir = dir($directory);
  334. while ($file = $mydir->read()) {
  335. if ((is_dir("$directory/$file")) AND ($file != ".") AND ($file != "..")) {
  336. if ($dir_name) {
  337. getDirFile("$directory/$file", "$dir_name/$file", $arr_file);
  338. } else {
  339. getDirFile("$directory/$file", "$file", $arr_file);
  340. }
  341. } else if (($file != ".") AND ($file != "..")) {
  342. if ($dir_name) {
  343. $arr_file[] = "$dir_name/$file";
  344. } else {
  345. $arr_file[] = "$file";
  346. }
  347. }
  348. }
  349. $mydir->close();
  350. return $arr_file;
  351. }
  352. }
  353. if (!function_exists('ey_scandir')) {
  354. /**
  355. * 部分空间为了安全起见,禁用scandir函数
  356. *
  357. * @param string $dir 路径
  358. * @return array
  359. */
  360. function ey_scandir($dir, $type = 'all')
  361. {
  362. if (function_exists('scandir')) {
  363. $files = scandir($dir);
  364. } else {
  365. $files = [];
  366. $mydir = dir($dir);
  367. while ($file = $mydir->read()) {
  368. $files[] = "$file";
  369. }
  370. $mydir->close();
  371. }
  372. $arr_file = [];
  373. foreach ($files as $key => $val) {
  374. if (($val != ".") AND ($val != "..")) {
  375. if ('all' == $type) {
  376. $arr_file[] = "$val";
  377. } else if ('file' == $type && is_file($val)) {
  378. $arr_file[] = "$val";
  379. } else if ('dir' == $type && is_dir($val)) {
  380. $arr_file[] = "$val";
  381. }
  382. }
  383. }
  384. return $arr_file;
  385. }
  386. }
  387. if (!function_exists('group_same_key')) {
  388. /**
  389. * 将二维数组以元素的某个值作为键,并归类数组
  390. *
  391. * array( array('name'=>'aa','type'=>'pay'), array('name'=>'cc','type'=>'pay') )
  392. * array('pay'=>array( array('name'=>'aa','type'=>'pay') , array('name'=>'cc','type'=>'pay') ))
  393. * @param $arr 数组
  394. * @param $key 分组值的key
  395. * @return array
  396. */
  397. function group_same_key($arr, $key)
  398. {
  399. $new_arr = array();
  400. foreach ($arr as $k => $v) {
  401. $new_arr[$v[$key]][] = $v;
  402. }
  403. return $new_arr;
  404. }
  405. }
  406. if (!function_exists('get_rand_str')) {
  407. /**
  408. * 获取随机字符串
  409. * @param int $randLength 长度
  410. * @param int $addtime 是否加入当前时间戳
  411. * @param int $includenumber 是否包含数字
  412. * @return string
  413. */
  414. function get_rand_str($randLength = 6, $addtime = 1, $includenumber = 0)
  415. {
  416. if (1 == $includenumber) {
  417. $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQEST123456789';
  418. } else if (2 == $includenumber) {
  419. $chars = '123456789';
  420. } else if (3 == $includenumber) {
  421. $chars = 'ABCDEFGHJKLMNPQEST123456789';
  422. } else {
  423. $chars = 'abcdefghijklmnopqrstuvwxyz';
  424. }
  425. $len = strlen($chars);
  426. $randStr = '';
  427. for ($i = 0; $i < $randLength; $i++) {
  428. $randStr .= $chars[rand(0, $len - 1)];
  429. }
  430. $tokenvalue = $randStr;
  431. if ($addtime) {
  432. $tokenvalue = $randStr . getTime();
  433. }
  434. return $tokenvalue;
  435. }
  436. }
  437. if (!function_exists('httpRequest')) {
  438. /**
  439. * CURL请求
  440. *
  441. * @param $url 请求url地址
  442. * @param $method 请求方法 get post
  443. * @param null $postfields post数据数组
  444. * @param array $headers 请求header信息
  445. * @param bool|false $debug 调试开启 默认false
  446. * @return mixed
  447. */
  448. function httpRequest($url, $method = "GET", $postfields = null, $headers = array(), $timeout = 30, $debug = false)
  449. {
  450. $method = strtoupper($method);
  451. $ci = curl_init();
  452. /* Curl settings */
  453. // curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); // 使用哪个版本
  454. curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
  455. curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
  456. // curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */
  457. curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); /* 设置cURL允许执行的最长秒数 */
  458. curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
  459. switch ($method) {
  460. case "POST":
  461. curl_setopt($ci, CURLOPT_POST, true);
  462. if (!empty($postfields)) {
  463. $tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields;
  464. curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
  465. }
  466. break;
  467. default:
  468. curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
  469. break;
  470. }
  471. $ssl = preg_match('/^https:\/\//i', $url) ? TRUE : FALSE;
  472. curl_setopt($ci, CURLOPT_URL, $url);
  473. if ($ssl) {
  474. curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
  475. curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
  476. }
  477. //curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/
  478. if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
  479. curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
  480. }
  481. curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/
  482. curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
  483. curl_setopt($ci, CURLINFO_HEADER_OUT, true);
  484. /*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */
  485. $response = curl_exec($ci);
  486. $requestinfo = curl_getinfo($ci);
  487. $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
  488. if ($debug) {
  489. echo "=====post data======\r\n";
  490. var_dump($postfields);
  491. echo "=====info===== \r\n";
  492. print_r($requestinfo);
  493. echo "=====response=====\r\n";
  494. print_r($response);
  495. }
  496. curl_close($ci);
  497. return $response;
  498. //return array($http_code, $response,$requestinfo);
  499. }
  500. }
  501. if (!function_exists('httpRequest2')) {
  502. /**
  503. * CURL请求
  504. *
  505. * @param $url 请求url地址
  506. * @param $method 请求方法 get post
  507. * @param null $postfields post数据数组
  508. * @param array $headers 请求header信息
  509. * @param bool|false $debug 调试开启 默认false
  510. * @return mixed
  511. */
  512. function httpRequest2($url, $method = "GET", $postfields = null, $headers = array(), $timeout = 30, $debug = false)
  513. {
  514. $method = strtoupper($method);
  515. $ci = curl_init();
  516. /* Curl settings */
  517. // curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); // 使用哪个版本
  518. curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
  519. curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
  520. // curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */
  521. curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); /* 设置cURL允许执行的最长秒数 */
  522. curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
  523. switch ($method) {
  524. case "POST":
  525. curl_setopt($ci, CURLOPT_POST, true);
  526. if (!empty($postfields)) {
  527. $web_basehost = request()->host(true);
  528. if (false !== filter_var($web_basehost, FILTER_VALIDATE_IP) || file_exists('./data/conf/multidomain.txt') || preg_match('/\.(my3w\.com)$/i', $web_basehost)) {
  529. $web_basehost = tpCache('web.web_basehost');
  530. }
  531. $web_basehost = preg_replace('/^(http(s)?:)?(\/\/)?([^\/\:]*)(.*)$/i', '${4}', $web_basehost);
  532. if (is_string($postfields)) {
  533. parse_str($postfields, $output);
  534. $output['domain'] = $web_basehost;
  535. $output['ip'] = serverIP();
  536. $tmpdatastr = http_build_query($output);
  537. } else {
  538. $postfields['domain'] = $web_basehost;
  539. $postfields['ip'] = serverIP();
  540. $tmpdatastr = http_build_query($postfields);
  541. }
  542. curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
  543. }
  544. break;
  545. default:
  546. curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
  547. break;
  548. }
  549. $ssl = preg_match('/^https:\/\//i', $url) ? TRUE : FALSE;
  550. curl_setopt($ci, CURLOPT_URL, $url);
  551. if ($ssl) {
  552. curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
  553. curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
  554. }
  555. //curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/
  556. if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
  557. curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
  558. }
  559. curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/
  560. curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
  561. curl_setopt($ci, CURLINFO_HEADER_OUT, true);
  562. /*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */
  563. $response = curl_exec($ci);
  564. $requestinfo = curl_getinfo($ci);
  565. $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
  566. if ($debug) {
  567. echo "=====post data======\r\n";
  568. var_dump($postfields);
  569. echo "=====info===== \r\n";
  570. print_r($requestinfo);
  571. echo "=====response=====\r\n";
  572. print_r($response);
  573. }
  574. curl_close($ci);
  575. return $response;
  576. //return array($http_code, $response,$requestinfo);
  577. }
  578. }
  579. if (!function_exists('check_mobile')) {
  580. /**
  581. * 检查手机号码格式
  582. *
  583. * @param $mobile 手机号码
  584. */
  585. function check_mobile($mobile)
  586. {
  587. if (preg_match('/1\d{10}$/', $mobile))
  588. return true;
  589. return false;
  590. }
  591. }
  592. if (!function_exists('check_telephone')) {
  593. /**
  594. * 检查固定电话
  595. *
  596. * @param $mobile
  597. * @return bool
  598. */
  599. function check_telephone($mobile)
  600. {
  601. if (preg_match('/^([0-9]{3,4}-)?[0-9]{7,8}$/', $mobile))
  602. return true;
  603. return false;
  604. }
  605. }
  606. if (!function_exists('check_email')) {
  607. /**
  608. * 检查邮箱地址格式
  609. *
  610. * @param $email 邮箱地址
  611. */
  612. function check_email($email)
  613. {
  614. if (filter_var($email, FILTER_VALIDATE_EMAIL))
  615. return true;
  616. return false;
  617. }
  618. }
  619. if (!function_exists('check_domain'))
  620. {
  621. /**
  622. * 校验域名格式
  623. *
  624. * @access public
  625. * @param string $operation 操作
  626. * @return string
  627. */
  628. function check_domain($domain = ''){
  629. $str="/^(?:[-A-za-z0-9_\x{4e00}-\x{9fa5}]+\.)+[-A-za-z0-9]{2,}$/u";
  630. if (!preg_match($str,$domain)){
  631. return false;
  632. }else{
  633. return true;
  634. }
  635. }
  636. }
  637. if (!function_exists('getSubstr')) {
  638. /**
  639. * 实现中文字串截取无乱码的方法
  640. *
  641. * @param string $string 字符串
  642. * @param intval $start 起始位置
  643. * @param intval $length 截取长度
  644. * @return string
  645. */
  646. function getSubstr($string = '', $start = 0, $length = NULL)
  647. {
  648. if (mb_strlen($string, 'utf-8') > $length) {
  649. $str = msubstr($string, $start, $length, true, 'utf-8');
  650. return $str;
  651. } else {
  652. return $string;
  653. }
  654. }
  655. }
  656. if (!function_exists('msubstr')) {
  657. /**
  658. * 字符串截取,支持中文和其他编码
  659. *
  660. * @param string $str 需要转换的字符串
  661. * @param string $start 开始位置
  662. * @param string $length 截取长度
  663. * @param string $suffix 截断显示字符
  664. * @param string $charset 编码格式
  665. * @return string
  666. */
  667. function msubstr($str = '', $start = 0, $length = NULL, $suffix = false, $charset = "utf-8")
  668. {
  669. if (function_exists("mb_substr")) {
  670. $slice = mb_substr($str, $start, $length, $charset);
  671. }
  672. elseif (function_exists('iconv_substr')) {
  673. $slice = iconv_substr($str, $start, $length, $charset);
  674. if (false === $slice) {
  675. $slice = '';
  676. }
  677. }
  678. else {
  679. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  680. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  681. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  682. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  683. preg_match_all($re[$charset], $str, $match);
  684. $slice = join("", array_slice($match[0], $start, $length));
  685. }
  686. $str_len = strlen($str); // 原字符串长度
  687. $slice_len = strlen($slice); // 截取字符串的长度
  688. if ($slice_len < $str_len) {
  689. $slice = $suffix ? $slice . '...' : $slice;
  690. }
  691. return $slice;
  692. }
  693. }
  694. if (!function_exists('html_msubstr')) {
  695. /**
  696. * 截取内容清除html之后的字符串长度,支持中文和其他编码
  697. *
  698. * @param string $str 需要转换的字符串
  699. * @param string $start 开始位置
  700. * @param string $length 截取长度
  701. * @param string $suffix 截断显示字符
  702. * @param string $charset 编码格式
  703. * @return string
  704. */
  705. function html_msubstr($str = '', $start = 0, $length = NULL, $suffix = false, $charset = "utf-8")
  706. {
  707. if (is_language() && 'cn' != get_current_lang()) {
  708. $length = $length * 2;
  709. }
  710. $str = eyou_htmlspecialchars_decode($str);
  711. $str = checkStrHtml($str);
  712. return msubstr($str, $start, $length, $suffix, $charset);
  713. }
  714. }
  715. if (!function_exists('text_msubstr')) {
  716. /**
  717. * 针对多语言截取,其他语言的截取是中文语言的2倍长度
  718. *
  719. * @param string $str 需要转换的字符串
  720. * @param string $start 开始位置
  721. * @param string $length 截取长度
  722. * @param string $suffix 截断显示字符
  723. * @param string $charset 编码格式
  724. * @return string
  725. */
  726. function text_msubstr($str = '', $start = 0, $length = NULL, $suffix = false, $charset = "utf-8")
  727. {
  728. if (is_language() && 'cn' != get_current_lang()) {
  729. $length = $length * 2;
  730. }
  731. return msubstr($str, $start, $length, $suffix, $charset);
  732. }
  733. }
  734. if (!function_exists('eyou_htmlspecialchars_decode')) {
  735. /**
  736. * 自定义只针对htmlspecialchars编码过的字符串进行解码
  737. *
  738. * @param string $str 需要转换的字符串
  739. * @param string $start 开始位置
  740. * @param string $length 截取长度
  741. * @param string $suffix 截断显示字符
  742. * @param string $charset 编码格式
  743. * @return string
  744. */
  745. function eyou_htmlspecialchars_decode($str = '')
  746. {
  747. if (is_string($str) && stripos($str, '&lt;') !== false && stripos($str, '&gt;') !== false) {
  748. $str = htmlspecialchars_decode($str);
  749. }
  750. return $str;
  751. }
  752. }
  753. if (!function_exists('isMobile')) {
  754. /**
  755. * 判断当前访问的用户是 PC端 还是 手机端 返回true 为手机端 false 为PC 端
  756. * 是否移动端访问
  757. *
  758. * @return boolean
  759. */
  760. function isMobile()
  761. {
  762. static $is_mobile = null;
  763. null === $is_mobile && $is_mobile = request()->isMobile();
  764. return $is_mobile;
  765. // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
  766. if (isset ($_SERVER['HTTP_X_WAP_PROFILE']))
  767. return true;
  768. // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
  769. if (isset ($_SERVER['HTTP_VIA'])) {
  770. // 找不到为flase,否则为true
  771. return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
  772. }
  773. // 脑残法,判断手机发送的客户端标志,兼容性有待提高
  774. if (isset ($_SERVER['HTTP_USER_AGENT'])) {
  775. $clientkeywords = array('nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile');
  776. // 从HTTP_USER_AGENT中查找手机浏览器的关键字
  777. if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT'])))
  778. return true;
  779. }
  780. // 协议法,因为有可能不准确,放到最后判断
  781. if (isset ($_SERVER['HTTP_ACCEPT'])) {
  782. // 如果只支持wml并且不支持html那一定是移动设备
  783. // 如果支持wml和html但是wml在html之前则是移动设备
  784. if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
  785. return true;
  786. }
  787. }
  788. return false;
  789. }
  790. }
  791. if (!function_exists('isWeixin')) {
  792. /**
  793. * 是否微信端访问
  794. *
  795. * @return boolean
  796. */
  797. function isWeixin()
  798. {
  799. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {
  800. return true;
  801. }
  802. return false;
  803. }
  804. }
  805. if (!function_exists('isWeixinApplets')) {
  806. /**
  807. * 是否微信端小程序访问
  808. *
  809. * @return boolean
  810. */
  811. function isWeixinApplets()
  812. {
  813. if (strpos($_SERVER['HTTP_USER_AGENT'], 'miniProgram') !== false) {
  814. return true;
  815. }
  816. return false;
  817. }
  818. }
  819. if (!function_exists('isQq')) {
  820. /**
  821. * 是否QQ端访问
  822. *
  823. * @return boolean
  824. */
  825. function isQq()
  826. {
  827. if (strpos($_SERVER['HTTP_USER_AGENT'], 'QQ') !== false) {
  828. return true;
  829. }
  830. return false;
  831. }
  832. }
  833. if (!function_exists('isAlipay')) {
  834. /**
  835. * 是否支付端访问
  836. *
  837. * @return boolean
  838. */
  839. function isAlipay()
  840. {
  841. if (strpos($_SERVER['HTTP_USER_AGENT'], 'AlipayClient') !== false) {
  842. return true;
  843. }
  844. return false;
  845. }
  846. }
  847. if (!function_exists('getFirstCharter')) {
  848. /**
  849. * php获取中文字符拼音首字母
  850. *
  851. * @param string $str 中文
  852. * @return boolean
  853. */
  854. function getFirstCharter($str)
  855. {
  856. if (empty($str)) {
  857. return '';
  858. }
  859. $fchar=ord($str[0]);
  860. if($fchar>=ord('A')&&$fchar<=ord('z')) return strtoupper($str[0]);
  861. $s1 = @iconv('UTF-8', 'gb2312', $str);
  862. $s2 = @iconv('gb2312', 'UTF-8', $s1);
  863. $s=$s2==$str?$s1:$str;
  864. $asc=ord($s[0])*256+ord($s[1])-65536;
  865. if ($asc >= -20319 && $asc <= -20284) return 'A';
  866. if ($asc >= -20283 && $asc <= -19776) return 'B';
  867. if ($asc >= -19775 && $asc <= -19219) return 'C';
  868. if ($asc >= -19218 && $asc <= -18711) return 'D';
  869. if ($asc >= -18710 && $asc <= -18527) return 'E';
  870. if ($asc >= -18526 && $asc <= -18240) return 'F';
  871. if ($asc >= -18239 && $asc <= -17923) return 'G';
  872. if ($asc >= -17922 && $asc <= -17418) return 'H';
  873. if ($asc >= -17417 && $asc <= -16475) return 'J';
  874. if ($asc >= -16474 && $asc <= -16213) return 'K';
  875. if ($asc >= -16212 && $asc <= -15641) return 'L';
  876. if ($asc >= -15640 && $asc <= -15166) return 'M';
  877. if ($asc >= -15165 && $asc <= -14923) return 'N';
  878. if ($asc >= -14922 && $asc <= -14915) return 'O';
  879. if ($asc >= -14914 && $asc <= -14631) return 'P';
  880. if ($asc >= -14630 && $asc <= -14150) return 'Q';
  881. if ($asc >= -14149 && $asc <= -14091) return 'R';
  882. if ($asc >= -14090 && $asc <= -13319) return 'S';
  883. if ($asc >= -13318 && $asc <= -12839) return 'T';
  884. if ($asc >= -12838 && $asc <= -12557) return 'W';
  885. if ($asc >= -12556 && $asc <= -11848) return 'X';
  886. if ($asc >= -11847 && $asc <= -11056) return 'Y';
  887. if ($asc >= -11055 && $asc <= -10247) return 'Z';
  888. return 'Z';
  889. }
  890. }
  891. if (!function_exists('pinyin_long')) {
  892. /**
  893. * 获取整条字符串汉字拼音首字母
  894. *
  895. * @param $zh
  896. * @return string
  897. */
  898. function pinyin_long($zh)
  899. {
  900. $ret = "";
  901. $s1 = iconv("UTF-8", "gb2312", $zh);
  902. $s2 = iconv("gb2312", "UTF-8", $s1);
  903. if ($s2 == $zh) {
  904. $zh = $s1;
  905. }
  906. for ($i = 0; $i < strlen($zh); $i++) {
  907. $s1 = substr($zh, $i, 1);
  908. $p = ord($s1);
  909. if ($p > 160) {
  910. $s2 = substr($zh, $i++, 2);
  911. $ret .= getFirstCharter($s2);
  912. } else {
  913. $ret .= $s1;
  914. }
  915. }
  916. return $ret;
  917. }
  918. }
  919. if (!function_exists('respose')) {
  920. /**
  921. * 参数 is_jsonp 为true,表示跨域ajax请求的返回值
  922. *
  923. * @param string $res 数组
  924. * @param bool $is_jsonp 是否跨域
  925. * @return string
  926. */
  927. function respose($res, $is_jsonp = false)
  928. {
  929. if (true === $is_jsonp) {
  930. exit(input('callback') . "(" . json_encode($res) . ")");
  931. } else {
  932. exit(json_encode($res,JSON_UNESCAPED_UNICODE));
  933. }
  934. }
  935. }
  936. if (!function_exists('urlsafe_b64encode')) {
  937. function urlsafe_b64encode($string)
  938. {
  939. $data = base64_encode($string);
  940. $data = str_replace(array('+', '/', '='), array('-', '_', ''), $data);
  941. return $data;
  942. }
  943. }
  944. if (!function_exists('getTime')) {
  945. /**
  946. * 获取当前时间戳
  947. *
  948. */
  949. function getTime()
  950. {
  951. return time();
  952. }
  953. }
  954. if (!function_exists('getMsectime')) {
  955. /**
  956. * 获取当前时间戳(精确到毫秒)
  957. *
  958. */
  959. function getMsectime()
  960. {
  961. list($msec, $sec) = explode(' ', microtime());
  962. $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
  963. return $msectime;
  964. }
  965. }
  966. if (!function_exists('trim_space')) {
  967. /**
  968. * 过滤前后空格等多种字符
  969. *
  970. * @param string $str 字符串
  971. * @param array $arr 特殊字符的数组集合
  972. * @return string
  973. */
  974. function trim_space($str, $arr = array())
  975. {
  976. if (empty($arr)) {
  977. $arr = array(' ', ' ');
  978. }
  979. foreach ($arr as $key => $val) {
  980. $str = preg_replace('/(^' . $val . ')|(' . $val . '$)/', '', $str);
  981. }
  982. return $str;
  983. }
  984. }
  985. if (!function_exists('func_preg_replace')) {
  986. /**
  987. * 替换指定的符号
  988. *
  989. * @param array $arr 特殊字符的数组集合
  990. * @param string $replacement 符号
  991. * @param string $str 字符串
  992. * @return string
  993. */
  994. function func_preg_replace($arr = array(), $replacement = ',', $str = '')
  995. {
  996. if (empty($arr)) {
  997. $arr = array(',');
  998. }
  999. foreach ($arr as $key => $val) {
  1000. if (is_array($replacement)) {
  1001. $replacevalue = isset($replacement[$key]) ? $replacement[$key] : current($replacement);
  1002. } else {
  1003. $replacevalue = $replacement;
  1004. }
  1005. $val = str_replace('/', '\/', $val);
  1006. $str = preg_replace('/(' . $val . ')/', $replacevalue, $str);
  1007. }
  1008. return $str;
  1009. }
  1010. }
  1011. if (!function_exists('db_create_in')) {
  1012. /**
  1013. * 创建像这样的查询: "IN('a','b')";
  1014. *
  1015. * @param mixed $item_list 列表数组或字符串,如果为字符串时,字符串只接受数字串
  1016. * @param string $field_name 字段名称
  1017. * @return string
  1018. */
  1019. function db_create_in($item_list, $field_name = '')
  1020. {
  1021. if (empty($item_list)) {
  1022. return $field_name . " IN ('') ";
  1023. } else {
  1024. if (!is_array($item_list)) {
  1025. $item_list = explode(',', $item_list);
  1026. foreach ($item_list as $k => $v) {
  1027. $item_list[$k] = intval($v);
  1028. }
  1029. }
  1030. $item_list = array_unique($item_list);
  1031. $item_list_tmp = '';
  1032. foreach ($item_list AS $item) {
  1033. if ($item !== '') {
  1034. $item_list_tmp .= $item_list_tmp ? ",'$item'" : "'$item'";
  1035. }
  1036. }
  1037. if (empty($item_list_tmp)) {
  1038. return $field_name . " IN ('') ";
  1039. } else {
  1040. return $field_name . ' IN (' . $item_list_tmp . ') ';
  1041. }
  1042. }
  1043. }
  1044. }
  1045. if (!function_exists('static_version')) {
  1046. /**
  1047. * 给静态文件追加版本号,实时刷新浏览器缓存
  1048. *
  1049. * @param string $file 为远程文件
  1050. * @return string
  1051. */
  1052. function static_version($file)
  1053. {
  1054. static $request = null;
  1055. null == $request && $request = \think\Request::instance();
  1056. // ---判断本地文件是否存在,否则返回false,以免@get_headers方法导致崩溃
  1057. if (is_http_url($file)) { // 判断http路径
  1058. if (preg_match('/^http(s?):\/\/' . $request->host(true) . '/i', $file)) { // 判断当前域名的本地服务器文件(这仅用于单台服务器,多台稍作修改便可)
  1059. // $pattern = '/^http(s?):\/\/([^.]+)\.([^.]+)\.([^\/]+)\/(.*)$/';
  1060. $pattern = '/^http(s?):\/\/([^\/]+)(.*)$/';
  1061. preg_match_all($pattern, $file, $matches);//正则表达式
  1062. if (!empty($matches)) {
  1063. $filename = $matches[count($matches) - 1][0];
  1064. if (!file_exists(realpath(ltrim($filename, '/')))) {
  1065. return false;
  1066. }
  1067. $file = $request->domain() . $filename;
  1068. }
  1069. }
  1070. $update_time = getTime();
  1071. } else {
  1072. if (!file_exists(realpath(ltrim($file, '/')))) {
  1073. return false;
  1074. }
  1075. try{
  1076. if ($request->controller() == 'Buildhtml') {
  1077. $update_time = getTime();
  1078. } else {
  1079. $fileStat = stat(ROOT_PATH . ltrim($file, '/'));
  1080. $update_time = !empty($fileStat['mtime']) ? $fileStat['mtime'] : getTime();
  1081. }
  1082. } catch (\Exception $e) {
  1083. $update_time = getTime();
  1084. }
  1085. }
  1086. // -------------end---------------
  1087. $parseStr = '';
  1088. $file = get_absolute_url(ROOT_DIR.$file); // 支持子目录
  1089. $update_time_str = !empty($update_time) ? '?t='.$update_time : '';
  1090. $type = strtolower(substr(strrchr($file, '.'), 1));
  1091. switch ($type) {
  1092. case 'js':
  1093. $parseStr .= '<script language="javascript" type="text/javascript" src="' . $file . $update_time_str . '"></script>';
  1094. break;
  1095. case 'css':
  1096. $parseStr .= '<link href="' . $file . $update_time_str . '" rel="stylesheet" media="screen" type="text/css" />';
  1097. break;
  1098. case 'ico':
  1099. $parseStr .= '<link rel="shortcut icon" href="' . $file . $update_time_str . '" />';
  1100. break;
  1101. }
  1102. return $parseStr;
  1103. }
  1104. }
  1105. if (!function_exists('tp_mkdir')) {
  1106. /**
  1107. * 递归创建目录
  1108. *
  1109. * @param string $path 目录路径,不带反斜杠
  1110. * @param intval $purview 目录权限码
  1111. * @return boolean
  1112. */
  1113. function tp_mkdir($path, $purview = 0777)
  1114. {
  1115. if (!is_dir($path)) {
  1116. tp_mkdir(dirname($path), $purview);
  1117. if (!mkdir($path, $purview)) {
  1118. return false;
  1119. }
  1120. }
  1121. return true;
  1122. }
  1123. }
  1124. if (!function_exists('format_bytes')) {
  1125. /**
  1126. * 格式化字节大小
  1127. *
  1128. * @param number $size 字节数
  1129. * @param string $delimiter 数字和单位分隔符
  1130. * @return string 格式化后的带单位的大小
  1131. */
  1132. function format_bytes($size, $delimiter = '')
  1133. {
  1134. $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
  1135. for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
  1136. return round($size, 2) . $delimiter . $units[$i];
  1137. }
  1138. }
  1139. if (!function_exists('unformat_bytes')) {
  1140. /**
  1141. * 反格式化字节大小
  1142. *
  1143. * @param number $size 格式化带单位的大小
  1144. */
  1145. function unformat_bytes($formatSize)
  1146. {
  1147. $size = 0;
  1148. if (preg_match('/^\d+P/i', $formatSize)) {
  1149. $size = intval($formatSize) * 1024 * 1024 * 1024 * 1024 * 1024;
  1150. } else if (preg_match('/^\d+T/i', $formatSize)) {
  1151. $size = intval($formatSize) * 1024 * 1024 * 1024 * 1024;
  1152. } else if (preg_match('/^\d+G/i', $formatSize)) {
  1153. $size = intval($formatSize) * 1024 * 1024 * 1024;
  1154. } else if (preg_match('/^\d+M/i', $formatSize)) {
  1155. $size = intval($formatSize) * 1024 * 1024;
  1156. } else if (preg_match('/^\d+K/i', $formatSize)) {
  1157. $size = intval($formatSize) * 1024;
  1158. } else if (preg_match('/^\d+B/i', $formatSize)) {
  1159. $size = intval($formatSize);
  1160. }
  1161. $size = strval($size);
  1162. return $size;
  1163. }
  1164. }
  1165. if (!function_exists('is_http_url')) {
  1166. /**
  1167. * 判断url是否完整的链接
  1168. *
  1169. * @param string $url 网址
  1170. * @return boolean
  1171. */
  1172. function is_http_url($url)
  1173. {
  1174. // preg_match("/^(http:|https:|ftp:|svn:)?(\/\/).*$/", $url, $match);
  1175. preg_match("/^((\w)*:)?(\/\/).*$/", $url, $match);
  1176. if (empty($match)) {
  1177. return false;
  1178. } else {
  1179. return true;
  1180. }
  1181. }
  1182. }
  1183. if (!function_exists('get_html_first_imgurl')) {
  1184. /**
  1185. * 获取文章内容html中第一张图片地址
  1186. *
  1187. * @param string $html html代码
  1188. * @return boolean
  1189. */
  1190. function get_html_first_imgurl($html)
  1191. {
  1192. $pattern = '~<img [^>]*[\s]?[\/]?[\s]?>~';
  1193. preg_match_all($pattern, $html, $matches);//正则表达式把图片的整个都获取出来了
  1194. $img_arr = $matches[0];//图片
  1195. $first_img_url = "";
  1196. if (!empty($img_arr)) {
  1197. $first_img = $img_arr[0];
  1198. $p = "#src=('|\")(.*)('|\")#isU";//正则表达式
  1199. preg_match_all($p, $first_img, $img_val);
  1200. if (isset($img_val[2][0])) {
  1201. $first_img_url = $img_val[2][0]; //获取第一张图片地址
  1202. }
  1203. }
  1204. return $first_img_url;
  1205. }
  1206. }
  1207. if (!function_exists('checkStrHtml')) {
  1208. /**
  1209. * 过滤Html标签
  1210. *
  1211. * @param string $string 内容
  1212. * @return string
  1213. */
  1214. function checkStrHtml($string, $replaces = [])
  1215. {
  1216. $string = str_replace("&nbsp;", " ", $string);
  1217. $string = trim_space($string);
  1218. $string = trim($string);
  1219. if (is_numeric($string)) return $string;
  1220. if (!isset($string) or empty($string)) return '';
  1221. $string = preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/', '', $string);
  1222. $string = ($string);
  1223. $string = strip_tags($string, ""); //清除HTML如<br />等代码
  1224. if (!empty($replaces)) {
  1225. $string = str_replace($replaces, "", $string);
  1226. }
  1227. $string = str_replace("\n", "", $string);//去掉空格和换行
  1228. $string = str_replace("\t", "", $string); //去掉制表符号
  1229. $string = str_replace(PHP_EOL, "", $string); //去掉回车换行符号
  1230. $string = str_replace("\r", "", $string); //去掉回车
  1231. $string = str_replace("'", "‘", $string); //替换单引号
  1232. $string = str_replace("&amp;", "&", $string);
  1233. $string = str_replace("=★", "", $string);
  1234. $string = str_replace("★=", "", $string);
  1235. $string = str_replace("★", "", $string);
  1236. $string = str_replace("☆", "", $string);
  1237. $string = str_replace("√", "", $string);
  1238. $string = str_replace("±", "", $string);
  1239. $string = str_replace("‖", "", $string);
  1240. $string = str_replace("×", "", $string);
  1241. $string = str_replace("∏", "", $string);
  1242. $string = str_replace("∷", "", $string);
  1243. $string = str_replace("⊥", "", $string);
  1244. $string = str_replace("∠", "", $string);
  1245. $string = str_replace("⊙", "", $string);
  1246. $string = str_replace("≈", "", $string);
  1247. $string = str_replace("≤", "", $string);
  1248. $string = str_replace("≥", "", $string);
  1249. $string = str_replace("∞", "", $string);
  1250. $string = str_replace("∵", "", $string);
  1251. $string = str_replace("♂", "", $string);
  1252. $string = str_replace("♀", "", $string);
  1253. $string = str_replace("°", "", $string);
  1254. $string = str_replace("¤", "", $string);
  1255. $string = str_replace("◎", "", $string);
  1256. $string = str_replace("◇", "", $string);
  1257. $string = str_replace("◆", "", $string);
  1258. $string = str_replace("→", "", $string);
  1259. $string = str_replace("←", "", $string);
  1260. $string = str_replace("↑", "", $string);
  1261. $string = str_replace("↓", "", $string);
  1262. $string = str_replace("▲", "", $string);
  1263. $string = str_replace("▼", "", $string);
  1264. // --过滤微信表情
  1265. $string = preg_replace_callback('/[\xf0-\xf7].{3}/', function ($r) {
  1266. return '';
  1267. }, $string);
  1268. return $string;
  1269. }
  1270. }
  1271. if (!function_exists('saveRemote')) {
  1272. /**
  1273. * 抓取远程图片
  1274. *
  1275. * @param string $fieldName 远程图片url
  1276. * @param string $savePath 存储在public/upload的子目录
  1277. * @return string
  1278. */
  1279. function saveRemote($fieldName, $savePath = 'temp/', $is_water = 1)
  1280. {
  1281. $allowFiles = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".svg", ".ico"];
  1282. $web_basehost = tpCache('web.web_basehost');
  1283. $parse_arr = parse_url($web_basehost);
  1284. $host = request()->host(true);
  1285. $imgUrl = htmlspecialchars($fieldName);
  1286. $imgUrl = str_replace("&amp;", "&", $imgUrl);
  1287. $imgUrl = preg_replace('/#/', '', $imgUrl);
  1288. // 插件列表
  1289. static $weappList = null;
  1290. if (null === $weappList) {
  1291. $weappList = \think\Db::name('weapp')->where([
  1292. 'status' => 1,
  1293. ])->cache(true, EYOUCMS_CACHE_TIME, 'weapp')
  1294. ->getAllWithIndex('code');
  1295. }
  1296. $storageDomain = ''; // 第三方存储的域名
  1297. if (!empty($weappList['Qiniuyun']['data'])) {
  1298. $qnyData = json_decode($weappList['Qiniuyun']['data'], true);
  1299. if (!empty($qnyData['domain'])) {
  1300. $storageDomain = $qnyData['domain'];
  1301. }
  1302. } else if (!empty($weappList['AliyunOss']['data'])) {
  1303. $ossData = json_decode($weappList['AliyunOss']['data'], true);
  1304. if (!empty($ossData['domain'])) {
  1305. $storageDomain = $ossData['domain'];
  1306. }
  1307. } else if (!empty($weappList['Cos']['data'])) {
  1308. $cosData = json_decode($weappList['Cos']['data'], true);
  1309. if (!empty($cosData['domain'])) {
  1310. $storageDomain = $cosData['domain'];
  1311. }
  1312. }
  1313. //http开头验证
  1314. if (strpos($imgUrl, "http") !== 0) {
  1315. $data = array(
  1316. 'state' => '链接不是http链接',
  1317. );
  1318. return json_encode($data);
  1319. }
  1320. //获取请求头并检测死链
  1321. $heads = @get_headers($imgUrl, 1);
  1322. if (empty($heads) || !(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
  1323. $data = array(
  1324. 'state' => '链接不可用',
  1325. );
  1326. return json_encode($data);
  1327. }
  1328. // 图片扩展名
  1329. $fileType = substr($heads['Content-Type'], -4, 4);
  1330. if (!preg_match("#\.(jpg|jpeg|gif|png|ico|bmp|webp|svg)#i", $fileType)) {
  1331. $filext = str_ireplace('image/', '', $heads['Content-Type']);
  1332. if ($fileType == 'image/gif' || $filext == 'gif') {
  1333. $fileType = ".gif";
  1334. } else if ($fileType == 'image/png' || $filext == 'png') {
  1335. $fileType = ".png";
  1336. } else if ($fileType == 'image/x-icon' || $filext == 'x-icon') {
  1337. $fileType = ".ico";
  1338. } else if ($fileType == 'image/bmp' || $filext == 'bmp') {
  1339. $fileType = ".bmp";
  1340. } else if ($fileType == 'image/webp' || $filext == 'webp') {
  1341. $fileType = ".webp";
  1342. } else if ($heads['Content-Type'] == 'image/svg+xml' || $filext == 'svg+xml') {
  1343. $fileType = ".svg";
  1344. } else {
  1345. $fileType = '.jpg';
  1346. }
  1347. }
  1348. $fileType = strtolower($fileType);
  1349. //格式验证(扩展名验证和Content-Type验证),链接contentType是否正确
  1350. $is_weixin_img = false;
  1351. if (preg_match("/^http(s?):\/\/(mmbiz.qpic.cn|thirdwx.qlogo.cn)\/(.*)/", $imgUrl) != 1) {
  1352. if (!in_array($fileType, $allowFiles) || (isset($heads['Content-Type']) && !stristr($heads['Content-Type'], "image/"))) {
  1353. $data = array(
  1354. 'state' => '链接contentType不正确',
  1355. );
  1356. return json_encode($data);
  1357. }
  1358. } else {
  1359. $is_weixin_img = true;
  1360. }
  1361. /*验证图片一句话木马*/
  1362. if (false === check_illegal($imgUrl,true)) {
  1363. $data = array(
  1364. 'state' => '疑似木马图片!!!',
  1365. );
  1366. return json_encode($data);
  1367. }
  1368. /*--end*/
  1369. // 本站图片 / 根网址图片 / 第三方存储插件的图片
  1370. if (preg_match("/\/\/({$host}|{$storageDomain}|{$parse_arr['host']})\//i", $imgUrl)) {
  1371. $arr = explode('/', $imgUrl);
  1372. $data = array(
  1373. 'state' => 'SUCCESS',
  1374. 'url' => $imgUrl,
  1375. 'title' => end($arr),
  1376. 'original' => '',
  1377. 'type' => strtolower(strrchr($imgUrl, '.')),
  1378. 'size' => 0,
  1379. 'width' => 0,
  1380. 'height' => 0,
  1381. 'mime' => '',
  1382. );
  1383. return json_encode($data);
  1384. }
  1385. //打开输出缓冲区并获取远程图片
  1386. ob_start();
  1387. $context = stream_context_create(
  1388. array('http' => array(
  1389. 'follow_location' => false // don't follow redirects
  1390. ))
  1391. );
  1392. readfile($imgUrl, false, $context);
  1393. $img = ob_get_contents();
  1394. ob_end_clean();
  1395. preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
  1396. $dirname = './' . UPLOAD_PATH . 'allimg/' . date('Ymd') . '/';
  1397. $file['oriName'] = $m ? $m[1] : "";
  1398. $file['filesize'] = strlen($img);
  1399. $file['ext'] = $fileType;
  1400. $users_id = 1;
  1401. if (session('?users_id')) {
  1402. $users_id = session('users_id');
  1403. } else if (session('?admin_id')) {
  1404. $users_id = session('admin_id');
  1405. }
  1406. $file['name'] = $users_id . '-' . dd2char(date("ymdHis") . mt_rand(100, 999)) . $file['ext'];
  1407. $file['fullName'] = $dirname . $file['name'];
  1408. $fullName = $file['fullName'];
  1409. //检查文件大小是否超出限制
  1410. if ($file['filesize'] >= 10240000) {
  1411. $data = array(
  1412. 'state' => '文件大小超出网站限制',
  1413. );
  1414. return json_encode($data);
  1415. }
  1416. //创建目录失败
  1417. if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
  1418. $data = array(
  1419. 'state' => '目录创建失败',
  1420. );
  1421. return json_encode($data);
  1422. } else if (!is_writeable($dirname)) {
  1423. $data = array(
  1424. 'state' => '目录没有写权限',
  1425. );
  1426. return json_encode($data);
  1427. }
  1428. //移动文件
  1429. if (!(file_put_contents($fullName, $img) && file_exists($fullName))) { //移动失败
  1430. $data = array(
  1431. 'state' => '写入文件内容错误',
  1432. );
  1433. return json_encode($data);
  1434. } else { //移动成功
  1435. $imgurl = substr($file['fullName'], 1);
  1436. $imageInfo = @getimagesize('.'.$imgurl);
  1437. $data = array(
  1438. 'state' => 'SUCCESS',
  1439. 'url' => ROOT_DIR.$imgurl,
  1440. 'title' => $file['name'],
  1441. 'original' => $file['oriName'],
  1442. 'type' => $file['ext'],
  1443. 'size' => $file['filesize'],
  1444. 'width' => !empty($imageInfo[0]) ? intval($imageInfo[0]) : 0,
  1445. 'height' => !empty($imageInfo[1]) ? intval($imageInfo[1]) : 0,
  1446. 'mime' => !empty($imageInfo['mime']) ? $imageInfo['mime'] : '',
  1447. );
  1448. try {
  1449. if (1 == $is_water) {
  1450. print_water($data['url']); // 添加水印
  1451. }
  1452. /*同步到第三方对象存储空间*/
  1453. $bucket_data = SynImageObjectBucket($data['url'], $weappList);
  1454. if (!empty($bucket_data['url']) && is_string($bucket_data['url'])) {
  1455. $data['url'] = $bucket_data['url'];
  1456. }
  1457. /*end*/
  1458. } catch (\Exception $e) {}
  1459. // 添加图片进数据库
  1460. $addData = [
  1461. 'aid' => 0,
  1462. 'type_id' => 0,
  1463. 'image_url' => $data['url'],
  1464. 'title' => '',
  1465. 'intro' => '',
  1466. 'width' => $data['width'],
  1467. 'height' => $data['height'],
  1468. 'filesize' => $data['size'],
  1469. 'mime' => $data['mime'],
  1470. 'users_id' => (int)session('admin_info.syn_users_id'),
  1471. 'sort_order' => 100,
  1472. 'add_time' => getTime(),
  1473. 'update_time' => getTime(),
  1474. ];
  1475. // \think\Db::name('uploads')->add($addData);
  1476. }
  1477. return json_encode($data);
  1478. }
  1479. }
  1480. if (!function_exists('func_common')) {
  1481. /**
  1482. * 自定义上传
  1483. *
  1484. * @param string $fileElementId 上传表单的ID
  1485. * @param string $path 存储在public/upload的子目录
  1486. * @param string $file_type 图片后缀名
  1487. * @return string
  1488. */
  1489. function func_common($fileElementId = 'uploadImage', $path = 'allimg', $file_type = "", $postFiles = [],$compressConf = [])
  1490. {
  1491. $lang = get_current_lang();
  1492. $file = !empty($postFiles) ? $postFiles : request()->file($fileElementId);
  1493. if (empty($file)) {
  1494. if ($lang == 'cn') {
  1495. $errmsg = '请选择上传图片';
  1496. } else if ($lang == 'zh') {
  1497. $errmsg = '請選擇上傳圖片';
  1498. } else {
  1499. $errmsg = 'Please select upload picture';
  1500. }
  1501. return ['errcode' => 1, 'errmsg' => $errmsg];
  1502. }
  1503. $validate = array();
  1504. // 文件大小限制
  1505. $validate['size'] = intval(tpCache('basic.file_size') * 1024 * 1024);
  1506. /*文件扩展名限制*/
  1507. $validate_ext = !empty($file_type) ? str_replace(',', '|', $file_type) : tpCache('basic.image_type');
  1508. $validate_ext = str_replace('|', ',', $validate_ext);
  1509. $validate['ext'] = explode(',', $validate_ext);
  1510. /*--end*/
  1511. //拓展名
  1512. $ext = pathinfo($file->getInfo('name'), PATHINFO_EXTENSION);
  1513. if (!in_array($ext, $validate['ext'])) {
  1514. if ($lang == 'cn') {
  1515. $errmsg = '上传图片后缀名必须为';
  1516. } else if ($lang == 'zh') {
  1517. $errmsg = '上傳圖片后綴名必須為';
  1518. } else {
  1519. $errmsg = 'Upload image suffix must be ';
  1520. }
  1521. return ['errcode' => 1, 'errmsg' => $errmsg . $validate_ext];
  1522. }
  1523. /*拓展名验证end*/
  1524. /*上传文件验证*/
  1525. if (!empty($validate)) {
  1526. $is_validate = $file->check($validate);
  1527. if ($is_validate === false) {
  1528. return ['errcode' => 1, 'errmsg' => $file->getError()];
  1529. }
  1530. }
  1531. /*--end*/
  1532. /*验证图片一句话木马*/
  1533. if (false === check_illegal($file->getInfo('tmp_name'))) {
  1534. if ($lang == 'cn') {
  1535. $errmsg = '疑似木马图片';
  1536. } else if ($lang == 'zh') {
  1537. $errmsg = '疑似木馬圖片';
  1538. } else {
  1539. $errmsg = 'Suspected Trojan images';
  1540. }
  1541. return ['errcode'=>1,'errmsg'=>$errmsg];
  1542. }
  1543. /*--end*/
  1544. $fileName = $file->getInfo('name');
  1545. // 提取文件名后缀
  1546. $file_ext = pathinfo($fileName, PATHINFO_EXTENSION);
  1547. // 提取出文件名,不包括扩展名
  1548. $newfileName = preg_replace('/\.([^\.]+)$/', '', $fileName);
  1549. // 过滤文件名.\/的特殊字符,防止利用上传漏洞
  1550. $newfileName = preg_replace('#(\\\|\/|\.)#i', '', $newfileName);
  1551. // 过滤后的新文件名
  1552. $fileName = $newfileName . '.' . $file_ext;
  1553. if (session('?users_id') && 'admin' != request()->module()) {
  1554. $users_id = session('users_id');
  1555. $savePath = UPLOAD_PATH.'user/'.session('users_id').'/';
  1556. } else {
  1557. $savePath = UPLOAD_PATH;
  1558. }
  1559. $savePath .= $path . '/' . date('Ymd/');
  1560. $return_url = "";
  1561. $info = $file->rule(function ($file) {
  1562. $users_id_tmp = 1;
  1563. if (session('?users_id') && 'admin' != request()->module()) {
  1564. $users_id_tmp = session('users_id');
  1565. } else if (session('?admin_id')) {
  1566. $users_id_tmp = session('admin_id');
  1567. }
  1568. return $users_id_tmp . '-' . dd2char(date("ymdHis") . mt_rand(100, 999));
  1569. })->move($savePath);
  1570. if ($info) {
  1571. $return_url = '/' . $savePath . $info->getSaveName();
  1572. // 重新制作一张图片,抹去任何可能有危害的数据
  1573. // $image = \think\Image::open('.'.$return_url);
  1574. // $image->save('.'.$return_url, null, 100);
  1575. }
  1576. // 是否要压缩图片
  1577. if (!empty($compressConf[0])) {
  1578. $return_url = func_thumb_img($return_url, $compressConf[0], $compressConf[1]);
  1579. }
  1580. if ($return_url) {
  1581. if ($lang == 'cn') {
  1582. $errmsg = '上传成功';
  1583. } else if ($lang == 'zh') {
  1584. $errmsg = '上傳成功';
  1585. } else {
  1586. $errmsg = 'Upload succeeded';
  1587. }
  1588. return ['errcode' => 0, 'errmsg' => $errmsg, 'img_url' => $return_url];
  1589. }
  1590. else {
  1591. if ($lang == 'cn') {
  1592. $errmsg = '上传失败';
  1593. } else if ($lang == 'zh') {
  1594. $errmsg = '上傳失敗';
  1595. } else {
  1596. $errmsg = 'Upload failed';
  1597. }
  1598. return ['errcode' => 1, 'errmsg' => $errmsg];
  1599. }
  1600. }
  1601. }
  1602. if (!function_exists('func_common_doc')) {
  1603. /**
  1604. * 自定义上传
  1605. *
  1606. * @param string $fileElementId 上传表单的ID
  1607. * @param string $path 存储在public/upload的子目录
  1608. * @param string $file_type 文件后缀名
  1609. * @return string
  1610. */
  1611. function func_common_doc($fileElementId = 'uploadFile', $path = 'soft', $file_type = "", $postFiles = [])
  1612. {
  1613. $lang = get_current_lang();
  1614. $file = !empty($postFiles) ? $postFiles : request()->file($fileElementId);
  1615. if (empty($file)) {
  1616. if ($lang == 'cn') {
  1617. $errmsg = '请选择上传文件';
  1618. } else if ($lang == 'zh') {
  1619. $errmsg = '請選擇上傳文件';
  1620. } else {
  1621. $errmsg = 'Please select upload file';
  1622. }
  1623. return ['errcode' => 1, 'errmsg' => $errmsg];
  1624. }
  1625. $validate = array();
  1626. // 文件大小限制
  1627. $validate['size'] = intval(tpCache('basic.file_size') * 1024 * 1024);
  1628. /*文件扩展名限制*/
  1629. $validate_ext = !empty($file_type) ? str_replace(',', '|', $file_type) : tpCache('basic.file_type');
  1630. $validate_ext = str_replace('|', ',', $validate_ext);
  1631. $validate['ext'] = explode(',', $validate_ext);
  1632. /*--end*/
  1633. //拓展名
  1634. $ext = pathinfo($file->getInfo('name'), PATHINFO_EXTENSION);
  1635. if (!in_array($ext, $validate['ext'])) {
  1636. if ($lang == 'cn') {
  1637. $errmsg = '上传文件后缀名必须为';
  1638. } else if ($lang == 'zh') {
  1639. $errmsg = '上傳文件后綴名必須為';
  1640. } else {
  1641. $errmsg = 'Upload file suffix must be ';
  1642. }
  1643. return ['errcode' => 1, 'errmsg' => $errmsg . $validate_ext];
  1644. }
  1645. /*拓展名验证end*/
  1646. /*上传文件验证*/
  1647. if (!empty($validate)) {
  1648. $is_validate = $file->check($validate);
  1649. if ($is_validate === false) {
  1650. return ['errcode' => 1, 'errmsg' => $file->getError()];
  1651. }
  1652. }
  1653. /*--end*/
  1654. $fileName = $file->getInfo('name');
  1655. // 提取文件名后缀
  1656. $file_ext = pathinfo($fileName, PATHINFO_EXTENSION);
  1657. // 提取出文件名,不包括扩展名
  1658. $newfileName = preg_replace('/\.([^\.]+)$/', '', $fileName);
  1659. // 过滤文件名.\/的特殊字符,防止利用上传漏洞
  1660. $newfileName = preg_replace('#(\\\|\/|\.)#i', '', $newfileName);
  1661. // 过滤后的新文件名
  1662. $fileName = $newfileName . '.' . $file_ext;
  1663. // 中文转码
  1664. // $newfileName = iconv("utf-8", "gb2312//IGNORE", $newfileName);
  1665. $savePath = $path . '/' . date('Ymd/');
  1666. $return_url = "";
  1667. $info = $file->rule(function ($file) {
  1668. // return md5(mt_rand());
  1669. $users_id = 1;
  1670. if (session('?users_id') && 'admin' != request()->module()) {
  1671. $users_id = session('users_id');
  1672. } else if (session('?admin_id')) {
  1673. $users_id = session('admin_id');
  1674. }
  1675. return $users_id . '-' . dd2char(date("ymdHis") . mt_rand(100, 999));
  1676. })->move(UPLOAD_PATH . $savePath);
  1677. if ($info) {
  1678. $return_url = '/' . UPLOAD_PATH . $savePath . $info->getSaveName();
  1679. }
  1680. if ($return_url) {
  1681. if ($lang == 'cn') {
  1682. $errmsg = '上传成功';
  1683. } else if ($lang == 'zh') {
  1684. $errmsg = '上傳成功';
  1685. } else {
  1686. $errmsg = 'Upload succeeded';
  1687. }
  1688. return ['errcode' => 0, 'errmsg' => $errmsg, 'img_url' => $return_url];
  1689. }
  1690. else {
  1691. if ($lang == 'cn') {
  1692. $errmsg = '上传失败';
  1693. } else if ($lang == 'zh') {
  1694. $errmsg = '上傳失敗';
  1695. } else {
  1696. $errmsg = 'Upload failed';
  1697. }
  1698. return ['errcode' => 1, 'errmsg' => $errmsg];
  1699. }
  1700. }
  1701. }
  1702. if (!function_exists('func_substr_replace')) {
  1703. /**
  1704. * 隐藏部分字符串
  1705. *
  1706. * @param string $str 字符串
  1707. * @param string $replacement 替换显示的字符
  1708. * @param intval $start 起始位置
  1709. * @param intval $length 隐藏长度
  1710. * @return string
  1711. */
  1712. function func_substr_replace($str, $replacement = '*', $start = 1, $length = 3)
  1713. {
  1714. $len = mb_strlen($str, 'utf-8');
  1715. if ($len > intval($start + $length)) {
  1716. $str1 = msubstr($str, 0, $start);
  1717. $str2 = msubstr($str, intval($start + $length), NULL);
  1718. } else {
  1719. $str1 = msubstr($str, 0, 1);
  1720. $str2 = msubstr($str, $len - 1, 1);
  1721. $length = $len - 2;
  1722. }
  1723. $new_str = $str1;
  1724. for ($i = 0; $i < $length; $i++) {
  1725. $new_str .= $replacement;
  1726. }
  1727. $new_str .= $str2;
  1728. return $new_str;
  1729. }
  1730. }
  1731. if (!function_exists('func_authcode')) {
  1732. /**
  1733. * 字符串加密解密
  1734. *
  1735. * @param unknown $string 明文或密文
  1736. * @param string $operation DECODE表示解密,其它表示加密
  1737. * @param string $key 密匙
  1738. * @param number $expiry 密文有效期
  1739. * @return string
  1740. */
  1741. function func_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
  1742. {
  1743. $ckey_length = 4;
  1744. $key = md5($key != '' ? $key : 'zxsdcrtkbrecxm');
  1745. $keya = md5(substr($key, 0, 16));
  1746. $keyb = md5(substr($key, 16, 16));
  1747. $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
  1748. $cryptkey = $keya . md5($keya . $keyc);
  1749. $key_length = strlen($cryptkey);
  1750. $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
  1751. $string_length = strlen($string);
  1752. $result = '';
  1753. $box = range(0, 255);
  1754. $rndkey = array();
  1755. for ($i = 0; $i <= 255; $i++) {
  1756. $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  1757. }
  1758. for ($j = $i = 0; $i < 256; $i++) {
  1759. $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  1760. $tmp = $box[$i];
  1761. $box[$i] = $box[$j];
  1762. $box[$j] = $tmp;
  1763. }
  1764. for ($a = $j = $i = 0; $i < $string_length; $i++) {
  1765. $a = ($a + 1) % 256;
  1766. $j = ($j + $box[$a]) % 256;
  1767. $tmp = $box[$a];
  1768. $box[$a] = $box[$j];
  1769. $box[$j] = $tmp;
  1770. $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  1771. }
  1772. if ($operation == 'DECODE') {
  1773. if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
  1774. return substr($result, 26);
  1775. } else {
  1776. return '';
  1777. }
  1778. } else {
  1779. return $keyc . str_replace('=', '', base64_encode($result));
  1780. }
  1781. }
  1782. }
  1783. if (!function_exists('get_pinyin')) {
  1784. /**
  1785. * 获取拼音以gbk编码为准
  1786. *
  1787. * @param string $str 字符串信息
  1788. * @param int $ishead 是否取头字母
  1789. * @param int $isclose 是否关闭字符串资源
  1790. * @return string
  1791. */
  1792. function get_pinyin($str, $ishead = 0, $isclose = 1)
  1793. {
  1794. try{
  1795. $s1 = iconv("UTF-8", "gb2312", $str);
  1796. $s2 = iconv("gb2312", "UTF-8", $s1);
  1797. if ($s2 == $str) {
  1798. $str = $s1;
  1799. }
  1800. static $pinyins = null;
  1801. $restr = '';
  1802. $str = trim($str);
  1803. $slen = strlen($str);
  1804. if ($slen < 2) {
  1805. return $str;
  1806. }
  1807. if (null === $pinyins) {
  1808. $pinyins = [];
  1809. $fp = fopen(DATA_PATH . 'conf/pinyin.dat', 'r');
  1810. while (!feof($fp)) {
  1811. $line = trim(fgets($fp));
  1812. $pinyins[$line[0] . $line[1]] = substr($line, 3, strlen($line) - 3);
  1813. }
  1814. fclose($fp);
  1815. }
  1816. for ($i = 0; $i < $slen; $i++) {
  1817. if (ord($str[$i]) > 0x80) {
  1818. $c = $str[$i] . $str[$i + 1];
  1819. $i++;
  1820. if (isset($pinyins[$c])) {
  1821. if ($ishead == 0) {
  1822. $restr .= $pinyins[$c];
  1823. } else {
  1824. $restr .= $pinyins[$c][0];
  1825. }
  1826. } else {
  1827. $restr .= "-";
  1828. }
  1829. } else if (preg_match("/[a-z0-9]/i", $str[$i])) {
  1830. $restr .= $str[$i];
  1831. } else {
  1832. $restr .= "-";
  1833. }
  1834. }
  1835. if ($isclose == 0) {
  1836. unset($pinyins);
  1837. }
  1838. return strtolower($restr);
  1839. }catch (\Exception $e){
  1840. return "";
  1841. }
  1842. }
  1843. }
  1844. if (!function_exists('filter_line_return')) {
  1845. /**
  1846. * 过滤换行回车符
  1847. *
  1848. * @param string $str 字符串信息
  1849. * @return string
  1850. */
  1851. function filter_line_return($str = '', $replace = '')
  1852. {
  1853. return str_replace(PHP_EOL, $replace, $str);
  1854. }
  1855. }
  1856. if (!function_exists('MyDate')) {
  1857. /**
  1858. * 时间转化日期格式
  1859. *
  1860. * @param string $format 日期格式
  1861. * @param intval $t 时间戳
  1862. * @return string
  1863. */
  1864. function MyDate($format = 'Y-m-d', $t = '')
  1865. {
  1866. if (!empty($t)) {
  1867. $t = date($format, $t);
  1868. }
  1869. return $t;
  1870. }
  1871. }
  1872. if (!function_exists('arctype_options')) {
  1873. /**
  1874. * 过滤和排序所有文章栏目,返回一个带有缩进级别的数组
  1875. *
  1876. * @param int $id 上级栏目ID
  1877. * @param array $arr 含有所有栏目的数组
  1878. * @param string $id_alias id键名
  1879. * @param string $pid_alias 父id键名
  1880. * @return void
  1881. */
  1882. function arctype_options($spec_id, $arr, $id_alias, $pid_alias)
  1883. {
  1884. $cat_options = array();
  1885. if (isset($cat_options[$spec_id])) {
  1886. return $cat_options[$spec_id];
  1887. }
  1888. if (!isset($cat_options[0])) {
  1889. $level = $last_id = 0;
  1890. $options = $id_array = $level_array = array();
  1891. while (!empty($arr)) {
  1892. foreach ($arr AS $key => $value) {
  1893. $id = $value[$id_alias];
  1894. if ($level == 0 && $last_id == 0) {
  1895. if ($value[$pid_alias] > 0) {
  1896. break;
  1897. }
  1898. $options[$id] = $value;
  1899. $options[$id]['level'] = $level;
  1900. $options[$id][$id_alias] = $id;
  1901. // $options[$id]['typename'] = $value['typename'];
  1902. unset($arr[$key]);
  1903. if ($value['has_children'] == 0) {
  1904. continue;
  1905. }
  1906. $last_id = $id;
  1907. $id_array = array($id);
  1908. $level_array[$last_id] = ++$level;
  1909. continue;
  1910. }
  1911. if ($value[$pid_alias] == $last_id) {
  1912. $options[$id] = $value;
  1913. $options[$id]['level'] = $level;
  1914. $options[$id][$id_alias] = $id;
  1915. // $options[$id]['typename'] = $value['typename'];
  1916. unset($arr[$key]);
  1917. if ($value['has_children'] > 0) {
  1918. if (end($id_array) != $last_id) {
  1919. $id_array[] = $last_id;
  1920. }
  1921. $last_id = $id;
  1922. $id_array[] = $id;
  1923. $level_array[$last_id] = ++$level;
  1924. }
  1925. } elseif ($value[$pid_alias] > $last_id) {
  1926. break;
  1927. }
  1928. }
  1929. $count = count($id_array);
  1930. if ($count > 1) {
  1931. $last_id = array_pop($id_array);
  1932. } elseif ($count == 1) {
  1933. if ($last_id != end($id_array)) {
  1934. $last_id = end($id_array);
  1935. } else {
  1936. $level = 0;
  1937. $last_id = 0;
  1938. $id_array = array();
  1939. continue;
  1940. }
  1941. }
  1942. if ($last_id && isset($level_array[$last_id])) {
  1943. $level = $level_array[$last_id];
  1944. } else {
  1945. $level = 0;
  1946. break;
  1947. }
  1948. }
  1949. $cat_options[0] = $options;
  1950. } else {
  1951. $options = $cat_options[0];
  1952. }
  1953. if (!$spec_id) {
  1954. return $options;
  1955. } else {
  1956. if (empty($options[$spec_id])) {
  1957. return array();
  1958. }
  1959. $spec_id_level = $options[$spec_id]['level'];
  1960. foreach ($options AS $key => $value) {
  1961. if ($key != $spec_id) {
  1962. unset($options[$key]);
  1963. } else {
  1964. break;
  1965. }
  1966. }
  1967. $spec_id_array = array();
  1968. foreach ($options AS $key => $value) {
  1969. if (($spec_id_level == $value['level'] && $value[$id_alias] != $spec_id) ||
  1970. ($spec_id_level > $value['level'])) {
  1971. break;
  1972. } else {
  1973. $spec_id_array[$key] = $value;
  1974. }
  1975. }
  1976. $cat_options[$spec_id] = $spec_id_array;
  1977. return $spec_id_array;
  1978. }
  1979. }
  1980. }
  1981. if (!function_exists('img_replace_url')) {
  1982. /**
  1983. * 内容图片地址替换成带有http地址
  1984. *
  1985. * @param string $content 内容
  1986. * @param string $imgurl 远程图片url
  1987. * @return string
  1988. */
  1989. function img_replace_url($content = '', $imgurl = '')
  1990. {
  1991. $pregRule = "/<img(.*?)src(\s*)=(\s*)[\'|\"](.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp|\.ico|\.webp]))[\'|\"](.*?)[\/]?(\s*)>/i";
  1992. $content = preg_replace($pregRule, '<img ${1} src="' . $imgurl . '" ${5} />', $content);
  1993. return $content;
  1994. }
  1995. }
  1996. if (!function_exists('getCmsVersion')) {
  1997. /**
  1998. * 获取当前CMS版本号
  1999. *
  2000. * @return string
  2001. */
  2002. function getCmsVersion()
  2003. {
  2004. $ver = 'v1.1.8';
  2005. $version_txt_path = ROOT_PATH . 'data/conf/version.txt';
  2006. if (file_exists($version_txt_path)) {
  2007. $fp = fopen($version_txt_path, 'r');
  2008. $content = fread($fp, filesize($version_txt_path));
  2009. fclose($fp);
  2010. $ver = $content ? $content : $ver;
  2011. } else {
  2012. $r = tp_mkdir(dirname($version_txt_path));
  2013. if ($r) {
  2014. $fp = fopen($version_txt_path, "w+") or die("请设置" . $version_txt_path . "的权限为777");
  2015. $web_version = tpCache('system.system_version');
  2016. $ver = !empty($web_version) ? $web_version : $ver;
  2017. if (fwrite($fp, $ver)) {
  2018. fclose($fp);
  2019. }
  2020. }
  2021. }
  2022. return $ver;
  2023. }
  2024. }
  2025. if (!function_exists('getVersion')) {
  2026. /**
  2027. * 获取当前各种版本号
  2028. *
  2029. * @return string
  2030. */
  2031. function getVersion($filename = 'version', $ver = 'v1.0.0', $is_write = false)
  2032. {
  2033. $version_txt_path = ROOT_PATH . 'data/conf/' . $filename . '.txt';
  2034. if (file_exists($version_txt_path) && false === $is_write) {
  2035. $fp = fopen($version_txt_path, 'r');
  2036. $content = fread($fp, filesize($version_txt_path));
  2037. fclose($fp);
  2038. $ver = $content ? $content : $ver;
  2039. } else if (!file_exists($version_txt_path) || true === $is_write) {
  2040. $r = tp_mkdir(dirname($version_txt_path));
  2041. if ($r) {
  2042. $fp = fopen($version_txt_path, "w+") or die("请设置" . $version_txt_path . "的权限为777");
  2043. if (fwrite($fp, $ver)) {
  2044. fclose($fp);
  2045. }
  2046. }
  2047. }
  2048. return $ver;
  2049. }
  2050. }
  2051. if (!function_exists('getWeappVersion')) {
  2052. /**
  2053. * 获取当前插件版本号
  2054. *
  2055. * @param string $ocde 插件标识
  2056. * @return string
  2057. */
  2058. function getWeappVersion($code)
  2059. {
  2060. $ver = 'v1.0';
  2061. $config_path = WEAPP_DIR_NAME . DS . $code . DS . 'config.php';
  2062. if (file_exists($config_path)) {
  2063. $config = include $config_path;
  2064. $ver = !empty($config['version']) ? $config['version'] : $ver;
  2065. } else {
  2066. die($code . "插件缺少" . $config_path . "配置文件");
  2067. }
  2068. return $ver;
  2069. }
  2070. }
  2071. if (!function_exists('strip_sql')) {
  2072. /**
  2073. * 转换SQL关键字
  2074. *
  2075. * @param unknown_type $string
  2076. * @return unknown
  2077. */
  2078. function strip_sql($string)
  2079. {
  2080. $pattern_arr = array(
  2081. "/(\s+)union(\s+)/i",
  2082. "/\bselect\b/i",
  2083. "/\bupdate\b/i",
  2084. "/\bdelete\b/i",
  2085. "/\boutfile\b/i",
  2086. // "/\bor\b/i",
  2087. "/\bchar\b/i",
  2088. "/\bconcat\b/i",
  2089. "/\btruncate\b/i",
  2090. "/\bdrop\b/i",
  2091. "/\binsert\b/i",
  2092. "/\brevoke\b/i",
  2093. "/\bgrant\b/i",
  2094. "/\breplace\b/i",
  2095. // "/\balert\b/i",
  2096. "/\brename\b/i",
  2097. // "/\bmaster\b/i",
  2098. "/\bdeclare\b/i",
  2099. // "/\bsource\b/i",
  2100. // "/\bload\b/i",
  2101. // "/\bcall\b/i",
  2102. "/\bexec\b/i",
  2103. "/\bdelimiter\b/i",
  2104. "/\bphar\b\:/i",
  2105. "/\bphar\b/i",
  2106. "/\@(\s*)\beval\b/i",
  2107. "/\beval\b/i",
  2108. "/\bonerror\b/i",
  2109. "/\bscript\b/i",
  2110. );
  2111. $replace_arr = array(
  2112. 'union',
  2113. 'select',
  2114. 'update',
  2115. 'delete',
  2116. 'outfile',
  2117. // 'or',
  2118. 'char',
  2119. 'concat',
  2120. 'truncate',
  2121. 'drop',
  2122. 'insert',
  2123. 'revoke',
  2124. 'grant',
  2125. 'replace',
  2126. // 'alert',
  2127. 'rename',
  2128. // 'master',
  2129. 'declare',
  2130. // 'source',
  2131. // 'load',
  2132. // 'call',
  2133. 'exec',
  2134. 'delimiter',
  2135. 'phar',
  2136. 'phar',
  2137. '@eval',
  2138. 'eval',
  2139. 'onerror',
  2140. 'script',
  2141. );
  2142. return is_array($string) ? array_map('strip_sql', $string) : preg_replace($pattern_arr, $replace_arr, $string);
  2143. }
  2144. }
  2145. if (!function_exists('get_weapp_class')) {
  2146. /**
  2147. * 获取插件类的类名
  2148. *
  2149. * @param strng $name 插件名
  2150. * @param strng $controller 控制器
  2151. * @return class
  2152. */
  2153. function get_weapp_class($name, $controller = '')
  2154. {
  2155. $controller = !empty($controller) ? $controller : $name;
  2156. $class = WEAPP_DIR_NAME . "\\{$name}\\controller\\{$controller}";
  2157. return $class;
  2158. }
  2159. }
  2160. if (!function_exists('view_logic')) {
  2161. /**
  2162. * 模型对应逻辑
  2163. * @param intval $aid 文档ID
  2164. * @param intval $channel 栏目ID
  2165. * @param intval $result 数组
  2166. * @param mix $allAttrInfo 附加表数据
  2167. * @return array
  2168. */
  2169. function view_logic($aid, $channel, $result = array(), $allAttrInfo = array())
  2170. {
  2171. $allAttrInfo_bool = $allAttrInfo;
  2172. $result['image_list'] = $result['attr_list'] = $result['file_list'] = array();
  2173. switch ($channel) {
  2174. case '2': // 产品模型
  2175. {
  2176. /*产品相册*/
  2177. if (true === $allAttrInfo_bool) {
  2178. $allAttrInfo = [];
  2179. $productImgModel = new \app\home\model\ProductImg;
  2180. $allAttrInfo['product_img'] = $productImgModel->getProImg([$aid]);
  2181. }
  2182. $image_list = !empty($allAttrInfo['product_img'][$aid]) ? $allAttrInfo['product_img'][$aid] : [];
  2183. // 支持子目录
  2184. foreach ($image_list as $k1 => $v1) {
  2185. $image_list[$k1]['image_url'] = handle_subdir_pic($v1['image_url']);
  2186. isset($v1['intro']) && $image_list[$k1]['intro'] = htmlspecialchars_decode($v1['intro']);
  2187. }
  2188. $result['image_list'] = $image_list;
  2189. /*--end*/
  2190. /*产品参数*/
  2191. if (true === $allAttrInfo_bool) {
  2192. $allAttrInfo = [];
  2193. $productAttrModel = new \app\home\model\ProductAttr;
  2194. $allAttrInfo['product_attr'] = $productAttrModel->getProAttr([$aid]);
  2195. }
  2196. $attr_list = !empty($allAttrInfo['product_attr'][$aid]) ? $allAttrInfo['product_attr'][$aid] : [];
  2197. $attr_list = model('LanguageAttr')->getBindValue($attr_list, 'product_attribute', get_main_lang()); // 获取多语言关联绑定的值
  2198. $result['attr_list'] = $attr_list;
  2199. /*--end*/
  2200. break;
  2201. }
  2202. case '3': // 图集模型
  2203. {
  2204. /*图集相册*/
  2205. if (true === $allAttrInfo_bool) {
  2206. $allAttrInfo = [];
  2207. $imagesUploadModel = new \app\home\model\ImagesUpload;
  2208. $allAttrInfo['images_upload'] = $imagesUploadModel->getImgUpload([$aid]);
  2209. }
  2210. $image_list = !empty($allAttrInfo['images_upload'][$aid]) ? $allAttrInfo['images_upload'][$aid] : [];
  2211. // 支持子目录
  2212. foreach ($image_list as $k1 => $v1) {
  2213. $image_list[$k1]['image_url'] = handle_subdir_pic($v1['image_url']);
  2214. isset($v1['intro']) && $image_list[$k1]['intro'] = htmlspecialchars_decode($v1['intro']);
  2215. }
  2216. $result['image_list'] = $image_list;
  2217. /*--end*/
  2218. break;
  2219. }
  2220. case '4': // 下载模型
  2221. {
  2222. /*下载资料列表*/
  2223. if (true === $allAttrInfo_bool) {
  2224. $allAttrInfo = [];
  2225. $downloadFileModel = new \app\home\model\DownloadFile;
  2226. $allAttrInfo['download_file'] = $downloadFileModel->getDownFile([$aid]);
  2227. }
  2228. $file_list = !empty($allAttrInfo['download_file'][$aid]) ? $allAttrInfo['download_file'][$aid] : [];
  2229. // 支持子目录
  2230. foreach ($file_list as $k1 => $v1) {
  2231. $file_list[$k1]['file_url'] = handle_subdir_pic($v1['file_url']);
  2232. if (empty($v1['file_size'])) {
  2233. $file_list[$k1]['file_size'] = '';
  2234. } else {
  2235. $file_list[$k1]['file_size'] = format_bytes($v1['file_size']);
  2236. }
  2237. }
  2238. $result['file_list'] = $file_list;
  2239. /*--end*/
  2240. /*下载权限*/
  2241. $arc_level_id = intval($result['arc_level_id']);
  2242. if (empty($arc_level_id)) {
  2243. $result['arc_level_name'] = '不限会员';
  2244. } else {
  2245. $result['arc_level_name'] = \think\Db::name('users_level')->where(['level_id'=>$arc_level_id])->getField('level_name');
  2246. }
  2247. /*--end*/
  2248. break;
  2249. }
  2250. case '5': // 视频模型
  2251. {
  2252. if (true === $allAttrInfo_bool) {
  2253. $allAttrInfo = [];
  2254. $mediaFileModel = new \app\home\model\MediaFile;
  2255. $allAttrInfo['video_file'] = $mediaFileModel->getMediaFile($aid);
  2256. }
  2257. $result['file_list'] = !empty($allAttrInfo['video_file']) ? $allAttrInfo['video_file'] : [];
  2258. //自定义视频字段
  2259. $channel_field = model('Channelfield')->getListByWhere(['channel_id'=>5,'dtype'=>'media']);
  2260. if (!empty($channel_field)) {
  2261. $request = request();
  2262. foreach ($channel_field as $key => $val) {
  2263. if (!empty($result[$key])) {
  2264. $result[$key] = json_decode($result[$key], true);
  2265. foreach ($result[$key] as $k => $v) {
  2266. if (!empty($v['file_url'])) {
  2267. $v['file_url'] = handle_subdir_pic($v['file_url'], 'media');
  2268. if (!is_http_url($v['file_url'])){
  2269. $v['file_url'] = $request->domain() .$v['file_url'];
  2270. }
  2271. }
  2272. $result[$key][$k] = $v;
  2273. }
  2274. }
  2275. }
  2276. }
  2277. isset($result['total_duration']) && $result['total_duration'] = gmSecondFormat($result['total_duration'], ':');
  2278. /*--end*/
  2279. /*播放权限*/
  2280. $arc_level_id = intval($result['arc_level_id']);
  2281. if (empty($arc_level_id)) {
  2282. $result['arc_level_name'] = '不限会员';
  2283. } else {
  2284. $result['arc_level_name'] = \think\Db::name('users_level')->where(['level_id'=>$arc_level_id])->getField('level_name');
  2285. }
  2286. /*--end*/
  2287. break;
  2288. }
  2289. default:
  2290. {
  2291. break;
  2292. }
  2293. }
  2294. return $result;
  2295. }
  2296. }
  2297. if (!function_exists('uncamelize')) {
  2298. /**
  2299. * 驼峰命名转下划线命名
  2300. * 思路:
  2301. * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
  2302. */
  2303. function uncamelize($camelCaps, $separator = '_')
  2304. {
  2305. return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
  2306. }
  2307. }
  2308. if (!function_exists('read_bidden_inc')) {
  2309. /**
  2310. * 读取被禁止外部访问的配置文件
  2311. *
  2312. */
  2313. function read_bidden_inc($phpfilepath = '')
  2314. {
  2315. $data = @file($phpfilepath);
  2316. if ($data) {
  2317. $data = !empty($data[1]) ? json_decode($data[1]) : [];
  2318. }
  2319. return $data;
  2320. }
  2321. }
  2322. if (!function_exists('write_bidden_inc')) {
  2323. /**
  2324. * 写入被禁止外部访问的配置文件
  2325. */
  2326. function write_bidden_inc($arr = array(), $phpfilepath = '')
  2327. {
  2328. $r = tp_mkdir(dirname($phpfilepath));
  2329. if ($r) {
  2330. $setting = "<?php die('forbidden'); ?>\n";
  2331. $setting .= json_encode($arr);
  2332. $setting = str_replace("\/", "/", $setting);
  2333. $incFile = fopen($phpfilepath, "w+");
  2334. if (fwrite($incFile, $setting)) {
  2335. fclose($incFile);
  2336. return true;
  2337. } else {
  2338. return false;
  2339. }
  2340. }
  2341. }
  2342. }
  2343. if (!function_exists('convert_js_array')) {
  2344. /**
  2345. * 将PHP数组转换成JS数组。
  2346. */
  2347. function convert_js_array($arr = array())
  2348. {
  2349. if (empty($arr)) {
  2350. return false;
  2351. }
  2352. $convert_js_array = "['";
  2353. foreach ($arr as $key => $val) {
  2354. if ($key > 0) {
  2355. $convert_js_array .= "','";
  2356. }
  2357. $convert_js_array .= $val;
  2358. }
  2359. $convert_js_array = $convert_js_array . "']";
  2360. return $convert_js_array;
  2361. }
  2362. }
  2363. if (!function_exists('GetUrlToDomain')) {
  2364. /**
  2365. * 取得根域名
  2366. * @param type $domain 域名
  2367. * @return string 返回根域名
  2368. */
  2369. function GetUrlToDomain($domain = '')
  2370. {
  2371. static $request = null;
  2372. null == $request && $request = \think\Request::instance();
  2373. $root = $request->rootDomain($domain);
  2374. return $root;
  2375. }
  2376. }
  2377. if (!function_exists('check_fix_pathinfo')) {
  2378. /**
  2379. * 判断支持pathinfo模式的路由,即是否支持伪静态
  2380. * @return boolean 布尔值
  2381. */
  2382. function check_fix_pathinfo()
  2383. {
  2384. static $is_fix_pathinfo = null;
  2385. if (null === $is_fix_pathinfo) {
  2386. $fix_pathinfo = ini_get('cgi.fix_pathinfo');
  2387. if (stristr(request()->host(), '.mylightsite.com') || ('' != $fix_pathinfo && 0 === $fix_pathinfo)) {
  2388. $is_fix_pathinfo = false;
  2389. } else {
  2390. $is_fix_pathinfo = true;
  2391. }
  2392. }
  2393. return $is_fix_pathinfo;
  2394. }
  2395. }
  2396. /**
  2397. * 生成一个随机字符
  2398. *
  2399. * @access public
  2400. * @param string $ddnum
  2401. * @return string
  2402. */
  2403. if (!function_exists('dd2char')) {
  2404. function dd2char($ddnum)
  2405. {
  2406. $ddnum = strval($ddnum);
  2407. $slen = strlen($ddnum);
  2408. $okdd = '';
  2409. $nn = '';
  2410. for ($i = 0; $i < $slen; $i++) {
  2411. if (isset($ddnum[$i + 1])) {
  2412. $n = $ddnum[$i] . $ddnum[$i + 1];
  2413. if (($n > 96 && $n < 123) || ($n > 64 && $n < 91)) {
  2414. $okdd .= chr($n);
  2415. $i++;
  2416. } else {
  2417. $okdd .= $ddnum[$i];
  2418. }
  2419. } else {
  2420. $okdd .= $ddnum[$i];
  2421. }
  2422. }
  2423. return $okdd;
  2424. }
  2425. }
  2426. if (!function_exists('friend_date')) {
  2427. /**
  2428. * 友好时间显示
  2429. * @param $time
  2430. * @return bool|string
  2431. */
  2432. function friend_date($time)
  2433. {
  2434. if (!$time)
  2435. return false;
  2436. $fdate = '';
  2437. $d = time() - intval($time);
  2438. $ld = $time - mktime(0, 0, 0, 0, 0, date('Y')); //得出年
  2439. $md = $time - mktime(0, 0, 0, date('m'), 0, date('Y')); //得出月
  2440. $byd = $time - mktime(0, 0, 0, date('m'), date('d') - 2, date('Y')); //前天
  2441. $yd = $time - mktime(0, 0, 0, date('m'), date('d') - 1, date('Y')); //昨天
  2442. $dd = $time - mktime(0, 0, 0, date('m'), date('d') + 0, date('Y')); //今天
  2443. $td = $time - mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')); //明天
  2444. $atd = $time - mktime(0, 0, 0, date('m'), date('d') + 2, date('Y')); //后天
  2445. if ($d == 0) {
  2446. $fdate = '刚刚';
  2447. } else {
  2448. switch ($d) {
  2449. case $d < $atd:
  2450. $fdate = date('Y年m月d日', $time);
  2451. break;
  2452. case $d < $td:
  2453. $fdate = '后天' . date('H:i', $time);
  2454. break;
  2455. case $d < 0:
  2456. $fdate = '明天' . date('H:i', $time);
  2457. break;
  2458. case $d < 60:
  2459. $fdate = $d . '秒前';
  2460. break;
  2461. case $d < 3600:
  2462. $fdate = floor($d / 60) . '分钟前';
  2463. break;
  2464. case $d < $dd:
  2465. $fdate = floor($d / 3600) . '小时前';
  2466. break;
  2467. case $d < $yd:
  2468. $fdate = '昨天' . date('H:i', $time);
  2469. break;
  2470. case $d < $byd:
  2471. $fdate = '前天' . date('H:i', $time);
  2472. break;
  2473. case $d < $md:
  2474. $fdate = date('m月d日 H:i', $time);
  2475. break;
  2476. case $d < $ld:
  2477. $fdate = date('m月d日', $time);
  2478. break;
  2479. default:
  2480. $fdate = date('Y年m月d日', $time);
  2481. break;
  2482. }
  2483. }
  2484. return $fdate;
  2485. }
  2486. }
  2487. /**
  2488. * 检查验证是否最新的模板
  2489. * @param $Url 查询的模板路径
  2490. * @param $String 查询是否存在的字符串
  2491. * @return 返回错误的字符串
  2492. */
  2493. if (!function_exists('VerifyLatestTemplate')) {
  2494. function VerifyLatestTemplate($Url = null, $String = [])
  2495. {
  2496. // 查询的模板路径
  2497. $Url = !empty($Url) ? $Url : './template/' . THEME_STYLE_PATH . '/view_product.htm';
  2498. // 查询是否存在的字符串
  2499. $String = !empty($String) ? $String : ['ReturnData', 'spec_name', 'spec_value', 'SpecClass', 'SpecData'];
  2500. // 获取出文件内容
  2501. $GetHtml = @file_get_contents($Url);
  2502. // 查询是否匹配
  2503. $ResultData = [];
  2504. foreach ($String as $value) {
  2505. if (strpos($GetHtml, $value) === false) {
  2506. array_push($ResultData, $value);
  2507. }
  2508. }
  2509. // 返回结果
  2510. return $ResultData;
  2511. }
  2512. }
  2513. /**
  2514. * 获取区域子域名URL
  2515. *
  2516. * @access public
  2517. * @param string $subDomain
  2518. * @return string
  2519. */
  2520. if (!function_exists('getRegionDomainUrl')) {
  2521. function getRegionDomainUrl($subDomain = '', $root_dir = true)
  2522. {
  2523. $domain = request()->host(true);
  2524. if (!empty($subDomain) && !preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i', $domain)) {
  2525. $domain = request()->subDomain($subDomain);
  2526. }
  2527. true === $root_dir && $domain .= ROOT_DIR;
  2528. return $domain;
  2529. }
  2530. }
  2531. /**
  2532. * 获取URl子域名,忽略IP地址
  2533. *
  2534. * @access public
  2535. * @param string $subDomain
  2536. * @return string
  2537. */
  2538. if (!function_exists('getSubDomain')) {
  2539. function getSubDomain($root_dir = true)
  2540. {
  2541. $domain = request()->host(true);
  2542. if (!empty($subDomain) && !preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i', $domain)) {
  2543. $rootDomain = request()->rootDomain();
  2544. $domain = $subDomain . '.' . $rootDomain;
  2545. }
  2546. true === $root_dir && $domain .= ROOT_DIR;
  2547. return $domain;
  2548. }
  2549. }
  2550. if (!function_exists('get_split_word')) {
  2551. /**
  2552. * 自动获取关键字
  2553. *
  2554. * @access public
  2555. * @param string $title 标题
  2556. * @param array $body 内容
  2557. * @return string
  2558. */
  2559. function get_split_word($title = '', $body = '')
  2560. {
  2561. vendor('splitword.autoload');
  2562. $keywords = '';
  2563. $kw = new keywords();
  2564. $keywords = $kw->GetSplitWord($title, $body);
  2565. return $keywords;
  2566. }
  2567. }
  2568. if (!function_exists('remote_to_local')) {
  2569. /**
  2570. * 远程图片本地化
  2571. *
  2572. * @access public
  2573. * @param string $body 内容
  2574. * @return string
  2575. */
  2576. function remote_to_local($body = '')
  2577. {
  2578. $web_basehost = tpCache('web.web_basehost');
  2579. $parse_arr = parse_url($web_basehost);
  2580. $host = request()->host(true);
  2581. $img_array = array();
  2582. preg_match_all("/src=[\"|'|\s]([^\"|^\'|^\s]*?)/isU", $body, $img_array);
  2583. $img_array = array_unique($img_array[1]);
  2584. foreach ($img_array as $key => $val) {
  2585. if (preg_match("/^http(s?):\/\/(mmbiz.qpic.cn|thirdwx.qlogo.cn)\/(.*)\?wx_fmt=(\w+)&/", $val) == 1) {
  2586. unset($img_array[$key]);
  2587. }
  2588. }
  2589. $dirname = './' . UPLOAD_PATH . 'allimg/' . date('Ymd/');
  2590. //创建目录失败
  2591. if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
  2592. return $body;
  2593. } else if (!is_writeable($dirname)) {
  2594. return $body;
  2595. }
  2596. // 插件列表
  2597. static $weappList = null;
  2598. if (null === $weappList) {
  2599. $weappList = \think\Db::name('weapp')->where([
  2600. 'status' => 1,
  2601. ])->cache(true, EYOUCMS_CACHE_TIME, 'weapp')
  2602. ->getAllWithIndex('code');
  2603. }
  2604. $storageDomain = ''; // 第三方存储的域名
  2605. if (!empty($weappList['Qiniuyun']['data'])) {
  2606. $qnyData = json_decode($weappList['Qiniuyun']['data'], true);
  2607. if (!empty($qnyData['domain'])) {
  2608. $storageDomain = $qnyData['domain'];
  2609. }
  2610. } else if (!empty($weappList['AliyunOss']['data'])) {
  2611. $ossData = json_decode($weappList['AliyunOss']['data'], true);
  2612. if (!empty($ossData['domain'])) {
  2613. $storageDomain = $ossData['domain'];
  2614. }
  2615. } else if (!empty($weappList['Cos']['data'])) {
  2616. $cosData = json_decode($weappList['Cos']['data'], true);
  2617. if (!empty($cosData['domain'])) {
  2618. $storageDomain = $cosData['domain'];
  2619. }
  2620. }
  2621. foreach ($img_array as $key => $value) {
  2622. $imgUrl = trim($value);
  2623. $imgUrl = preg_replace('/#/', '', $imgUrl);
  2624. // 本站图片 / 根网址图片 / 第三方存储插件的图片
  2625. if (!empty($parse_arr['host'])){
  2626. if (preg_match("/\/\/({$host}|{$storageDomain}|{$parse_arr['host']})\//i", $imgUrl)) {
  2627. continue;
  2628. }
  2629. }else{
  2630. if (preg_match("/\/\/({$host}|{$storageDomain})\//i", $imgUrl)) {
  2631. continue;
  2632. }
  2633. }
  2634. // 不是合法链接
  2635. if (!preg_match("#^http(s?):\/\/#i", $imgUrl)) {
  2636. continue;
  2637. }
  2638. $heads = @get_headers($imgUrl, 1);
  2639. // 获取请求头并检测死链
  2640. if (empty($heads) || !(stristr($heads[0], "200") && !stristr($heads[0], "304"))) {
  2641. continue;
  2642. }
  2643. // 图片扩展名
  2644. $fileType = substr($heads['Content-Type'], -4, 4);
  2645. if (!preg_match("#\.(jpg|jpeg|gif|png|ico|bmp|webp|svg)#i", $fileType)) {
  2646. $filext = str_ireplace('image/', '', $heads['Content-Type']);
  2647. if ($fileType == 'image/gif' || $filext == 'gif') {
  2648. $fileType = ".gif";
  2649. } else if ($fileType == 'image/png' || $filext == 'png') {
  2650. $fileType = ".png";
  2651. } else if ($fileType == 'image/x-icon' || $filext == 'x-icon') {
  2652. $fileType = ".ico";
  2653. } else if ($fileType == 'image/bmp' || $filext == 'bmp') {
  2654. $fileType = ".bmp";
  2655. } else if ($fileType == 'image/webp' || $filext == 'webp') {
  2656. $fileType = ".webp";
  2657. } else if ($heads['Content-Type'] == 'image/svg+xml' || $filext == 'svg+xml') {
  2658. $fileType = ".svg";
  2659. } else {
  2660. $fileType = '.jpg';
  2661. }
  2662. }
  2663. $fileType = strtolower($fileType);
  2664. //格式验证(扩展名验证和Content-Type验证),链接contentType是否正确
  2665. $is_weixin_img = false;
  2666. if (preg_match("/^http(s?):\/\/(mmbiz.qpic.cn|thirdwx.qlogo.cn)\/(.*)/", $imgUrl) != 1) {
  2667. $allowFiles = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".webp", ".svg"];
  2668. if (!in_array($fileType, $allowFiles) || (isset($heads['Content-Type']) && !stristr($heads['Content-Type'], "image/"))) {
  2669. continue;
  2670. }
  2671. } else {
  2672. $is_weixin_img = true;
  2673. }
  2674. //打开输出缓冲区并获取远程图片
  2675. ob_start();
  2676. $context = stream_context_create(
  2677. array('http' => array(
  2678. 'follow_location' => false // don't follow redirects
  2679. ))
  2680. );
  2681. readfile($imgUrl, false, $context);
  2682. $img = ob_get_contents();
  2683. ob_end_clean();
  2684. preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
  2685. $file = [];
  2686. $file['oriName'] = $m ? $m[1] : "";
  2687. $file['filesize'] = strlen($img);
  2688. $file['ext'] = $fileType;
  2689. $file['name'] = session('admin_id') . '-' . dd2char(date("ymdHis") . mt_rand(100, 999)) . $file['ext'];
  2690. $file['fullName'] = $dirname . $file['name'];
  2691. $fullName = $file['fullName'];
  2692. //检查文件大小是否超出限制
  2693. if ($file['filesize'] >= 20480000) {
  2694. continue;
  2695. }
  2696. //移动文件
  2697. if (!(file_put_contents($fullName, $img) && file_exists($fullName))) { //移动失败
  2698. continue;
  2699. }
  2700. $fileurl = ROOT_DIR . substr($file['fullName'], 1);
  2701. // if ($is_weixin_img == true) {
  2702. // $fileurl .= "?";
  2703. // }
  2704. /* $search = array("'".$imgUrl."'", '"'.$imgUrl.'"');
  2705. $replace = array($fileurl, $fileurl);
  2706. $body = str_replace($search, $replace, $body);*/
  2707. // 添加水印
  2708. try {
  2709. print_water($fileurl);
  2710. /*同步到第三方对象存储空间*/
  2711. $bucket_data = SynImageObjectBucket($fileurl, $weappList);
  2712. if (!empty($bucket_data['url']) && is_string($bucket_data['url'])) {
  2713. $fileurl = $bucket_data['url'];
  2714. }
  2715. /*end*/
  2716. } catch (\Exception $e) {}
  2717. $body = str_replace($imgUrl, $fileurl, $body);
  2718. // 添加图片进数据库
  2719. $img_info = @getimagesize('.'.substr($file['fullName'], 1));
  2720. $width = isset($img_info[0]) ? $img_info[0] : 0;
  2721. $height = isset($img_info[1]) ? $img_info[1] : 0;
  2722. $mime = isset($img_info['mime']) ? $img_info['mime'] : '';
  2723. $addData[] = [
  2724. 'aid' => 0,
  2725. 'type_id' => 0,
  2726. 'image_url' => $fileurl,
  2727. 'title' => '',
  2728. 'intro' => '',
  2729. 'width' => $width,
  2730. 'height' => $height,
  2731. 'filesize' => $file['filesize'],
  2732. 'mime' => $mime,
  2733. 'users_id' => (int)session('admin_info.syn_users_id'),
  2734. 'sort_order' => 100,
  2735. 'add_time' => getTime(),
  2736. 'update_time' => getTime(),
  2737. ];
  2738. }
  2739. // 添加图片进数据库
  2740. // !empty($addData) && \think\Db::name('uploads')->insertAll($addData);
  2741. return $body;
  2742. }
  2743. }
  2744. if (!function_exists('replace_links')) {
  2745. /**
  2746. * 清除非站内链接
  2747. *
  2748. * @access public
  2749. * @param string $body 内容
  2750. * @param array $allow_urls 允许的超链接
  2751. * @return string
  2752. */
  2753. function replace_links($body, $allow_urls = array())
  2754. {
  2755. // 读取允许的超链接设置
  2756. $host = request()->host(true);
  2757. $rootDomain = request()->rootDomain();
  2758. if (!empty($allow_urls)) {
  2759. $allow_urls = array_merge([$host,$rootDomain], $allow_urls);
  2760. } else {
  2761. $basic_body_allowurls = tpCache('basic.basic_body_allowurls');
  2762. if (!empty($basic_body_allowurls)) {
  2763. $allowurls = explode(PHP_EOL, $basic_body_allowurls);
  2764. $allow_urls = array_merge([$host,$rootDomain], $allowurls);
  2765. } else {
  2766. $allow_urls = [$host,$rootDomain];
  2767. }
  2768. }
  2769. $web_basehost = tpCache('web.web_basehost');
  2770. $parse_arr = parse_url($web_basehost);
  2771. if (!empty($parse_arr['host'])) {
  2772. array_push($allow_urls, $parse_arr['host']);
  2773. }
  2774. $host_rule = join('|', $allow_urls);
  2775. $host_rule = preg_replace("#[\n\r]#", '', $host_rule);
  2776. $host_rule = str_replace('.', "\\.", $host_rule);
  2777. $host_rule = str_replace('/', "\\/", $host_rule);
  2778. $arr = '';
  2779. preg_match_all("#<a([^>]*)>(.*)<\/a>#iU", $body, $arr);
  2780. if (is_array($arr[0])) {
  2781. $rparr = array();
  2782. $tgarr = array();
  2783. foreach ($arr[0] as $i => $v) {
  2784. if ( ($host_rule != '' && preg_match('#' . $host_rule . '#i', $arr[1][$i])) || !preg_match('/(\s+)href(\s*)=(\s*)([\'|\"]?)((\w)*:)?(\/\/)/i', $arr[1][$i]) ) {
  2785. continue;
  2786. } else {
  2787. $rparr[] = $v;
  2788. $tgarr[] = $arr[2][$i];
  2789. }
  2790. }
  2791. if (!empty($rparr)) {
  2792. $body = str_replace($rparr, $tgarr, $body);
  2793. }
  2794. }
  2795. $arr = $rparr = $tgarr = '';
  2796. return $body;
  2797. }
  2798. }
  2799. if (!function_exists('print_water')) {
  2800. /**
  2801. * 给图片增加水印
  2802. *
  2803. * @access public
  2804. * @param string $imgpath 不带子目录的图片路径
  2805. * @return string
  2806. */
  2807. function print_water($imgpath = '')
  2808. {
  2809. try {
  2810. static $water = null;
  2811. null === $water && $water = tpCache('water');
  2812. if (empty($imgpath) || $water['is_mark'] != 1) {
  2813. return $imgpath;
  2814. }
  2815. $imgpath = handle_subdir_pic($imgpath, 'img', false, true); // 支持子目录
  2816. $imgresource = "." . $imgpath;
  2817. $image = \think\Image::open($imgresource);
  2818. if ($image->width() > $water['mark_width'] && $image->height() > $water['mark_height']) {
  2819. if ($water['mark_type'] == 'text') {
  2820. //$image->text($water['mark_txt'],ROOT_PATH.'public/static/common/font/hgzb.ttf',20,'#000000',9)->save($imgresource);
  2821. $ttf = ROOT_PATH . 'public/static/common/font/hgzb.ttf';
  2822. if (file_exists($ttf)) {
  2823. $size = $water['mark_txt_size'] ? $water['mark_txt_size'] : 30;
  2824. $color = $water['mark_txt_color'] ?: '#000000';
  2825. if (!preg_match('/^#[0-9a-fA-F]{6}$/', $color)) {
  2826. $color = '#000000';
  2827. }
  2828. $transparency = intval((100 - $water['mark_degree']) * (127 / 100));
  2829. $color .= dechex($transparency);
  2830. $image->text($water['mark_txt'], $ttf, $size, $color, $water['mark_sel'])->save($imgresource);
  2831. }
  2832. } else {
  2833. $water['mark_img'] = preg_replace('/\?(.*)$/i', '', $water['mark_img']);
  2834. $water['mark_img'] = handle_subdir_pic($water['mark_img'], 'img', false, true); // 支持子目录
  2835. //$image->water(".".$water['mark_img'],9,$water['mark_degree'])->save($imgresource);
  2836. $waterPath = "." . $water['mark_img'];
  2837. if (eyPreventShell($waterPath) && file_exists($waterPath)) {
  2838. $waterImgInfo = @getimagesize($waterPath);
  2839. $waterImgW = !empty($waterImgInfo[0]) ? $waterImgInfo[0] : 1000000;
  2840. $waterImgH = !empty($waterImgInfo[1]) ? $waterImgInfo[1] : 1000000;
  2841. if ($image->width() > $waterImgW && $image->height() > $waterImgH) {
  2842. $quality = $water['mark_quality'] ? $water['mark_quality'] : 80;
  2843. $waterTempPath = dirname($waterPath) . '/temp_' . basename($waterPath);
  2844. $image->open($waterPath)->save($waterTempPath, null, $quality);
  2845. $image->water($waterTempPath, $water['mark_sel'], $water['mark_degree'])->save($imgresource);
  2846. @unlink($waterTempPath);
  2847. }
  2848. }
  2849. }
  2850. }
  2851. } catch (\Exception $e) {
  2852. }
  2853. }
  2854. }
  2855. if (!function_exists('filterNickname')) {
  2856. // 过滤微信表情符号
  2857. function filterNickname($nickname = '')
  2858. {
  2859. $nickname = preg_replace('/[\x{1F600}-\x{1F64F}]/u', '', $nickname);
  2860. $nickname = preg_replace('/[\x{1F300}-\x{1F5FF}]/u', '', $nickname);
  2861. $nickname = preg_replace('/[\x{1F680}-\x{1F6FF}]/u', '', $nickname);
  2862. $nickname = preg_replace('/[\x{2600}-\x{26FF}]/u', '', $nickname);
  2863. $nickname = preg_replace('/[\x{2700}-\x{27BF}]/u', '', $nickname);
  2864. $nickname = str_replace(array('"', '\''), '', $nickname);
  2865. return addslashes(trim($nickname));
  2866. }
  2867. }
  2868. if (!function_exists('mchStrCode')) {
  2869. /**
  2870. * 加密函数
  2871. *
  2872. * @access public
  2873. * @param string $string 字符串
  2874. * @param string $operation 操作
  2875. * @return string
  2876. */
  2877. function mchStrCode($string, $operation = 'ENCODE', $auth_code = '')
  2878. {
  2879. if (empty($auth_code)) {
  2880. $auth_code = get_auth_code();
  2881. }
  2882. $key_length = 4;
  2883. $expiry = 0;
  2884. $key = md5($auth_code);
  2885. $fixedkey = md5($key);
  2886. $egiskeys = md5(substr($fixedkey, 16, 16));
  2887. $runtokey = $key_length ? ($operation == 'ENCODE' ? substr(md5(microtime(true)), -$key_length) : substr($string, 0, $key_length)) : '';
  2888. $keys = md5(substr($runtokey, 0, 16) . substr($fixedkey, 0, 16) . substr($runtokey, 16) . substr($fixedkey, 16));
  2889. $string = $operation == 'ENCODE' ? sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $egiskeys), 0, 16) . $string : base64_decode(substr($string, $key_length));
  2890. $i = 0;
  2891. $result = '';
  2892. $string_length = strlen($string);
  2893. for ($i = 0; $i < $string_length; $i++) {
  2894. $result .= chr(ord($string[$i]) ^ ord($keys[$i % 32]));
  2895. }
  2896. if ($operation == 'ENCODE') {
  2897. return $runtokey . str_replace('=', '', base64_encode($result));
  2898. } else {
  2899. $str1 = substr($result, 0, 10);
  2900. if(version_compare(PHP_VERSION,'8.0.0','>')) {
  2901. $str1 = !empty($str1) ? $str1 : 0;
  2902. }
  2903. if (($str1 == 0 || intval($str1) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $egiskeys), 0, 16)) {
  2904. return substr($result, 26);
  2905. } else {
  2906. return '';
  2907. }
  2908. }
  2909. }
  2910. }
  2911. if (!function_exists('html_httpimgurl')) {
  2912. /**
  2913. * html内容里的图片地址替换成http路径
  2914. * @param string $content 内容
  2915. * @return string
  2916. */
  2917. function html_httpimgurl($content = '', $timeVersion = false)
  2918. {
  2919. if (!empty($content)) {
  2920. $t = '';
  2921. if (true === $timeVersion) {
  2922. $t = '?t='.getTime();
  2923. }
  2924. $pregRule = "/<img(.*?)src(\s*)=(\s*)[\'|\"]\/(.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp|\.ico|\.webp]))[\'|\"](.*?)[\/]?(\s*)>/i";
  2925. $content = preg_replace($pregRule, '<img ${1} src="' . request()->domain() . '/${4}'.$t.'" ${5} />', $content);
  2926. }
  2927. return $content;
  2928. }
  2929. }
  2930. if (!function_exists('getCityLocation')) {
  2931. /**
  2932. * 根据IP获取地区
  2933. * @param string $ip [description]
  2934. * @return [type] [description]
  2935. */
  2936. function getCityLocation($ip = '')
  2937. {
  2938. if (preg_match('/127\.0\.\d{1,3}\.\d{1,3}/i', $ip) || preg_match('/192\.168\.\d{1,3}\.\d{1,3}/i', $ip) || 'localhost' == $ip) {
  2939. return ['location'=>'本地局域网'];
  2940. } else {
  2941. try {
  2942. $res1 = httpRequest("https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query={$ip}&resource_id=6006&t=" . getMsectime());
  2943. $res1 = iconv('GB2312', 'UTF-8', $res1);
  2944. $res1 = json_decode($res1, true);
  2945. if ($res1 && $res1['status'] == '0') {
  2946. $data = current($res1['data']);
  2947. \think\Cookie::set("city_localtion", $data);
  2948. return $data;
  2949. }
  2950. /* $res1 = httpRequest("http://ip.taobao.com/service/getIpInfo.php?ip=" .$ip);
  2951. $res1 = json_decode($res1,true);
  2952. if($res1 && $res1['code'] == '0'){
  2953. \think\Cookie::set("city_localtion", $res1['data']);
  2954. return $res1['data'];
  2955. }*/
  2956. } catch (\Exception $e) {}
  2957. }
  2958. return false;
  2959. }
  2960. }
  2961. if (!function_exists('Convert_GCJ02_To_BD09')) {
  2962. /**
  2963. * 中国正常GCJ02坐标---->百度地图BD09坐标
  2964. * 腾讯地图用的也是GCJ02坐标
  2965. * @param double $lat 纬度
  2966. * @param double $lng 经度
  2967. */
  2968. function Convert_GCJ02_To_BD09($lat = 0, $lng = 0)
  2969. {
  2970. $x_pi = M_PI;
  2971. $x_pi = $x_pi * 3000.0 / 180.0;
  2972. $x = $lng;
  2973. $y = $lat;
  2974. $z = sqrt($x * $x + $y * $y) + 0.00002 * sin($y * $x_pi);
  2975. $theta = atan2($y, $x) + 0.000003 * cos($x * $x_pi);
  2976. $lng = $z * cos($theta) + 0.0065;
  2977. $lat = $z * sin($theta) + 0.006;
  2978. return ['lng' => $lng, 'lat' => $lat];
  2979. }
  2980. }
  2981. if (!function_exists('Convert_BD09_To_GCJ02')) {
  2982. /*
  2983. * 百度地图BD09坐标---->中国正常GCJ02坐标
  2984. * 腾讯地图用的也是GCJ02坐标
  2985. * @param double $lat 纬度
  2986. * @param double $lng 经度
  2987. * @return array();
  2988. */
  2989. function Convert_BD09_To_GCJ02($lat = 0, $lng = 0)
  2990. {
  2991. $x_pi = M_PI;
  2992. $x_pi = $x_pi * 3000.0 / 180.0;
  2993. $x = $lng - 0.0065;
  2994. $y = $lat - 0.006;
  2995. $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
  2996. $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
  2997. $lng = $z * cos($theta);
  2998. $lat = $z * sin($theta);
  2999. return ['lat' => $lat, 'lng' => $lng];
  3000. }
  3001. }
  3002. if (!function_exists('get_filename')) {
  3003. /**
  3004. * 上传附件类型前台处理url获得文件名称(带拓展名)
  3005. * @param string $value
  3006. * @return mixed
  3007. */
  3008. function get_filename($value='')
  3009. {
  3010. $value_arr = explode('/',$value);
  3011. $str = end($value_arr);
  3012. return $str;
  3013. }
  3014. }
  3015. if (!function_exists('gmSecondFormat')) {
  3016. /**
  3017. * 将秒数转为时间格式
  3018. * @param intval $seconds 秒数
  3019. * @param string $separator 分隔符
  3020. * @return mixed
  3021. */
  3022. function gmSecondFormat($seconds = 0, $separator = '')
  3023. {
  3024. $timeStr = '';
  3025. if (empty($seconds)) {
  3026. if (empty($separator)) {
  3027. $timeStr = "00小时00分钟00秒";
  3028. } else {
  3029. $timeStr = "00{$separator}00{$separator}00";
  3030. }
  3031. } else {
  3032. $seconds = intval($seconds);
  3033. $hours = intval($seconds/3600);
  3034. if ($hours < 10) {
  3035. $hours = '0'.$hours;
  3036. }
  3037. if (empty($separator)) {
  3038. $timeStr = $hours."小时".gmdate('i分钟s秒', $seconds);
  3039. } else {
  3040. $timeStr = $hours.$separator.gmdate("i{$separator}s", $seconds);
  3041. }
  3042. }
  3043. return $timeStr;
  3044. }
  3045. }
  3046. if (!function_exists('checkAuthRule')) {
  3047. /**
  3048. * 验证代理贴牌的功能权限
  3049. * @return mixed
  3050. */
  3051. function checkAuthRule($id)
  3052. {
  3053. $admin_id = session('admin_id');
  3054. $info = \think\Db::name('admin')->where('admin_id',$admin_id)->field('parent_id,role_id')->find();
  3055. if (!empty($info) && empty($info['parent_id']) && $info['role_id'] == -1){
  3056. //创始人拥有无上权限
  3057. return true;
  3058. }
  3059. $php_auth_function = tpCache('php.php_auth_function');
  3060. $auth_function = !empty($php_auth_function) ? explode(',', $php_auth_function) : [];
  3061. if (!empty($auth_function) && !in_array($id, $auth_function)){
  3062. return false;
  3063. }else{
  3064. return true;
  3065. }
  3066. }
  3067. }
  3068. if (!function_exists('check_illegal')) {
  3069. /**
  3070. * 检测上传图片是否包含有非法代码
  3071. * @return mixed
  3072. */
  3073. function check_illegal($image = '', $is_force = false)
  3074. {
  3075. $weapp_check_illegal_open = tpCache('weapp.weapp_check_illegal_open');
  3076. if ($is_force || (is_numeric($weapp_check_illegal_open) && strval($weapp_check_illegal_open) === '0')) {
  3077. try {
  3078. $hexCode = file_get_contents($image);
  3079. if (preg_match('#file_put_contents#i', $hexCode) || preg_match('#__HALT_COMPILER()#i', $hexCode) || preg_match('#/script>#i', $hexCode) || preg_match('#<([^?]*)\?php#i', $hexCode) || preg_match('#<\?\=(\s+)#i', $hexCode) || preg_match('#(\s+)language(\s*)=(\s*)("|\')?php("|\')?#i', $hexCode)) {
  3080. return false;
  3081. }
  3082. // if (file_exists($image)) {
  3083. // $resource = fopen($image, 'rb');
  3084. // $fileSize = filesize($image);
  3085. // fseek($resource, 0);
  3086. // $hexCode = fread($resource, $fileSize);
  3087. // fclose($resource);
  3088. // if (preg_match('#file_put_contents#i', $hexCode) || preg_match('#__HALT_COMPILER()#i', $hexCode) || preg_match('#/script>#i', $hexCode) || preg_match('#<([^?]*)\?php#i', $hexCode) || preg_match('#<\?\=(\s+)#i', $hexCode)) {
  3089. // return false;
  3090. // }
  3091. // }
  3092. } catch (\Exception $e) {
  3093. return false;
  3094. }
  3095. }
  3096. return true;
  3097. }
  3098. }
  3099. if (!function_exists('getUsersTplVersion')) {
  3100. /**
  3101. * 获取当前会员模板的版本号
  3102. *
  3103. * @return string
  3104. */
  3105. function getUsersTplVersion()
  3106. {
  3107. $ver = 'v1';
  3108. $web_users_tpl_theme = tpCache('web.web_users_tpl_theme');
  3109. if (empty($web_users_tpl_theme)) {
  3110. $web_users_tpl_theme = 'users';
  3111. }
  3112. $version_txt_path = "./template/".THEME_STYLE_PATH."/{$web_users_tpl_theme}/version.txt";
  3113. if (file_exists(realpath($version_txt_path))) {
  3114. $fp = fopen($version_txt_path, 'r');
  3115. $content = fread($fp, filesize($version_txt_path));
  3116. fclose($fp);
  3117. $ver = $content ? $content : $ver;
  3118. }
  3119. return $ver;
  3120. }
  3121. }
  3122. if (!function_exists('getUsersTpl2xVersion')) {
  3123. /**
  3124. * 获取当前V2会员模板的版本号
  3125. *
  3126. * @return string
  3127. */
  3128. function getUsersTpl2xVersion()
  3129. {
  3130. $ver = '';
  3131. $web_users_tpl_theme = tpCache('web.web_users_tpl_theme');
  3132. if (empty($web_users_tpl_theme)) {
  3133. $web_users_tpl_theme = 'users';
  3134. }
  3135. $version_txt_path = "./template/".THEME_STYLE_PATH."/{$web_users_tpl_theme}/version_2x.txt";
  3136. if (file_exists(realpath($version_txt_path))) {
  3137. $fp = fopen($version_txt_path, 'r');
  3138. $content = fread($fp, filesize($version_txt_path));
  3139. fclose($fp);
  3140. $ver = $content ? $content : $ver;
  3141. }
  3142. return $ver;
  3143. }
  3144. }
  3145. if (!function_exists('hex2rgba')) {
  3146. /**
  3147. * 16进制颜色代码转换为rgba,rgb格式
  3148. *
  3149. * @return string
  3150. */
  3151. function hex2rgba($color, $opacity = false, $raw = false) {
  3152. $default = 'rgb(0,0,0)';
  3153. //Return default if no color provided
  3154. if(empty($color))
  3155. return $default;
  3156. //Sanitize $color if "#" is provided
  3157. if ($color[0] == '#' ) {
  3158. $color = substr( $color, 1 );
  3159. }
  3160. //Check if color has 6 or 3 characters and get values
  3161. if (strlen($color) == 6) {
  3162. $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
  3163. } elseif ( strlen( $color ) == 3 ) {
  3164. $hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
  3165. } else {
  3166. return $default;
  3167. }
  3168. //Convert hexadec to rgb
  3169. $rgb = array_map('hexdec', $hex);
  3170. if($raw){
  3171. if($opacity){
  3172. if(abs($opacity) > 1) $opacity = 1.0;
  3173. array_push($rgb, $opacity);
  3174. }
  3175. $output = $rgb;
  3176. }else{
  3177. //Check if opacity is set(rgba or rgb)
  3178. if($opacity){
  3179. if(abs($opacity) > 1)
  3180. $opacity = 1.0;
  3181. $output = 'rgba('.implode(",",$rgb).','.$opacity.')';
  3182. } else {
  3183. $output = 'rgb('.implode(",",$rgb).')';
  3184. }
  3185. }
  3186. //Return rgb(a) color string
  3187. return $output;
  3188. }
  3189. }
  3190. if (!function_exists('is_local_ip'))
  3191. {
  3192. /**
  3193. * 简单判断当前访问站点是否本地
  3194. * @param string $domain 不带协议的域名
  3195. * @return boolean
  3196. */
  3197. function is_local_ip($domain = '')
  3198. {
  3199. $is_local = false;
  3200. $sip = serverIP();
  3201. $domain = !empty($domain) ? $domain : request()->host();
  3202. if (preg_match('/127\.0\.\d{1,3}\.\d{1,3}/i', $domain) || preg_match('/192\.168\.\d{1,3}\.\d{1,3}/i', $domain) || 'localhost' == $domain || '127.0.0.1' == $sip) {
  3203. $is_local = true;
  3204. }
  3205. return $is_local;
  3206. }
  3207. }
  3208. if (!function_exists('upload_max_filesize'))
  3209. {
  3210. /**
  3211. * 获取当前可上传文件大小
  3212. * @return boolean
  3213. */
  3214. function upload_max_filesize()
  3215. {
  3216. $file_size = tpCache('basic.file_size');
  3217. $postsize = @ini_get('file_uploads') ? ini_get('post_max_size') : -1;
  3218. $fileupload = @ini_get('file_uploads') ? ini_get('upload_max_filesize') : -1;
  3219. $min_size = intval($file_size) < intval($postsize) ? $file_size : $postsize;
  3220. $min_size = intval($min_size) < intval($fileupload) ? $min_size : $fileupload;
  3221. $upload_max_filesize = intval($min_size) * 1024 * 1024;
  3222. return $upload_max_filesize;
  3223. }
  3224. }
  3225. if (!function_exists('image_accept_arr'))
  3226. {
  3227. /**
  3228. * 上传图片扩展名对应的accept,应用于选择上传图片时,系统自带的选择框里只列出指定图片扩展名的图片文件
  3229. * @return boolean
  3230. */
  3231. function image_accept_arr($image_type = '')
  3232. {
  3233. $accept = '';
  3234. if (!empty($image_type)) {
  3235. if (is_string($image_type)) {
  3236. $image_type_arr = explode(',', $image_type);
  3237. } else {
  3238. $image_type_arr = $image_type;
  3239. }
  3240. foreach ($image_type_arr as $key => $val) {
  3241. if ($key > 0) $accept .= ',';
  3242. if ('icon' == $val) {
  3243. $accept .= "image/x-icon";
  3244. } else if ('svg' == $val) {
  3245. $accept .= "image/svg+xml";
  3246. } else {
  3247. $accept .= "image/{$val}";
  3248. }
  3249. }
  3250. } else {
  3251. $accept = 'image/gif,image/jpg,image/jpeg,image/png,image/bmp,image/x-icon,image/webp,image/svg+xml';
  3252. }
  3253. return $accept;
  3254. }
  3255. }
  3256. if (!function_exists('filename_preg_match'))
  3257. {
  3258. /**
  3259. * 正则判断文件名、文件路径的字符串是否合法
  3260. * @return boolean
  3261. */
  3262. function filename_preg_match($filename = '')
  3263. {
  3264. if (preg_match('/(<|>|\"|\*|\:|\?|\|)/i', $filename)) {
  3265. return false;
  3266. }
  3267. return true;
  3268. }
  3269. }