ASP Classic blog framework - BrainOrdure
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

602 行
19KB

  1. <%
  2. Function QuoteValue(val)
  3. if IsWrappedInSingleQuotes(val) then
  4. QuoteValue = val
  5. Exit Function
  6. end if
  7. Select Case VarType(val)
  8. Case vbString
  9. QuoteValue = "'" & Replace(val, "'", "''") & "'"
  10. Case vbDate
  11. if conn.Provider = "Microsoft.Jet.OLEDB.4.0" or conn.Provider = "Microsoft.ACE.OLEDB.12.0" then
  12. QuoteValue = "#" & FormatDateTime(val, 0) & "#"
  13. else
  14. ' SQL Server
  15. QuoteValue = "'" & FormatDateTime(val, 0) & "'"
  16. end if
  17. Case vbNull, vbEmpty
  18. QuoteValue = "Null"
  19. Case vbBoolean
  20. ' Return boolean values without quotes
  21. QuoteValue = "'" & CStr(val) & "'"
  22. Case Else
  23. If IsNumeric(val) Then
  24. QuoteValue = CLng(val)
  25. Else
  26. QuoteValue = CStr(val)
  27. End If
  28. End Select
  29. End Function
  30. Public Function GetAppSetting(key)
  31. Dim cacheKey, xml, nodes, node, i
  32. cacheKey = "AppSetting_" & key
  33. ' Check Application cache first for performance
  34. If Not IsEmpty(Application(cacheKey)) Then
  35. GetAppSetting = Application(cacheKey)
  36. Exit Function
  37. End If
  38. ' Load from web.config only if not cached
  39. Set xml = Server.CreateObject("Microsoft.XMLDOM")
  40. xml.Load(Server.MapPath("web.config"))
  41. Set nodes = xml.selectNodes("//appSettings/add")
  42. For i = 0 To nodes.Length - 1
  43. Set node = nodes.Item(i)
  44. If node.getAttribute("key") = key Then
  45. GetAppSetting = node.getAttribute("value")
  46. ' Cache the value for subsequent requests
  47. Application.Lock
  48. Application(cacheKey) = GetAppSetting
  49. Application.Unlock
  50. Exit Function
  51. End If
  52. Next
  53. GetAppSetting = "nothing"
  54. End Function
  55. Public Sub ShowServerVariables
  56. Dim varName, htmlTable
  57. htmlTable = "<table border='1' cellspacing='0' cellpadding='5'>"
  58. htmlTable = htmlTable & "<thead><tr><th>Variable Name</th><th>Value</th></tr></thead><tbody>"
  59. ' Loop through all server variables
  60. For Each varName In Request.ServerVariables
  61. htmlTable = htmlTable & "<tr>"
  62. htmlTable = htmlTable & "<td>" & Server.HTMLEncode(varName) & "</td>"
  63. htmlTable = htmlTable & "<td>" & Server.HTMLEncode(Request.ServerVariables(varName)) & "</td>"
  64. htmlTable = htmlTable & "</tr>"
  65. Next
  66. htmlTable = htmlTable & "</tbody></table>"
  67. ' Output the HTML table
  68. Response.Write(htmlTable)
  69. End Sub
  70. '------------------------------------------------------------------------------
  71. ' Utility: IIf Function for VBScript
  72. ' Usage: result = IIf(condition, trueValue, falseValue)
  73. '------------------------------------------------------------------------------
  74. Function IIf(condition, trueValue, falseValue)
  75. On Error Resume Next
  76. If CBool(condition) Then
  77. IIf = trueValue
  78. Else
  79. IIf = falseValue
  80. End If
  81. If Err.Number <> 0 Then
  82. ' Optional: handle or log error in conversion/evaluation
  83. Err.Clear
  84. End If
  85. On Error GoTo 0
  86. End Function
  87. '-----------------------------
  88. ' Utility: Generic Error Reporter
  89. '-----------------------------
  90. Public Sub ErrorCheck(context)
  91. If Err.Number <> 0 Then
  92. Dim errHtml
  93. errHtml = "<div style='padding:10px; border:2px solid red; background:#fdd; font-family:Verdana; font-size:12px;'>"
  94. errHtml = errHtml & "<strong>Error occurred" & IIf(Not IsEmpty(context) And context <> "", ": " & context, "") & "</strong><br />"
  95. errHtml = errHtml & "<em>Time:</em> " & Now() & "<br />"
  96. errHtml = errHtml & "<em>Number:</em> " & Err.Number & "<br />"
  97. errHtml = errHtml & "<em>Description:</em> " & Server.HTMLEncode(Err.Description) & "<br />"
  98. If Len(Err.Source) > 0 Then
  99. errHtml = errHtml & "<em>Source:</em> " & Server.HTMLEncode(Err.Source) & "<br />"
  100. End If
  101. errHtml = errHtml & "</div>"
  102. Response.Write errHtml
  103. Err.Clear
  104. End If
  105. End Sub
  106. '------------------------------------------------------------------------------
  107. ' Utility: TrimQueryParams
  108. ' Removes everything from the first "?" or "&" onward.
  109. ' Usage:
  110. ' CleanPath = TrimQueryParams(rawPath)
  111. '------------------------------------------------------------------------------
  112. Function TrimQueryParams(rawPath)
  113. Dim posQ, posA, cutPos
  114. ' find the first occurrences of "?" and "&"
  115. posQ = InStr(rawPath, "?")
  116. posA = InStr(rawPath, "&")
  117. ' determine the earliest cut position (>0)
  118. If posQ > 0 And posA > 0 Then
  119. cutPos = IIf(posQ < posA, posQ, posA)
  120. ElseIf posQ > 0 Then
  121. cutPos = posQ
  122. ElseIf posA > 0 Then
  123. cutPos = posA
  124. Else
  125. cutPos = 0
  126. End If
  127. ' if found, return up to just before that char
  128. If cutPos > 0 Then
  129. TrimQueryParams = Left(rawPath, cutPos - 1)
  130. Else
  131. TrimQueryParams = rawPath
  132. End If
  133. End Function
  134. Sub Destroy(o)
  135. if isobject(o) then
  136. if not o is nothing then
  137. on error resume next
  138. o.close
  139. on error goto 0
  140. set o = nothing
  141. end if
  142. end if
  143. End Sub
  144. 'prepends indents
  145. Private Sub puti(v)
  146. put Spaces(m_indent) & v
  147. End Sub
  148. Sub put(v)
  149. Select Case typename(v)
  150. Case "LinkedList_Class" : response.write join(v.TO_Array, ", ")
  151. Case "DynamicArray_Class" : response.write JoinList(v)
  152. Case "Variant()" : response.write join(v, ", ")
  153. Case else : response.write v
  154. End Select
  155. End Sub
  156. Sub put_
  157. put "<br>"
  158. End Sub
  159. Sub putl(v)
  160. put v
  161. put_
  162. End Sub
  163. '---------------------------------------------------------------------------------------------------------------------
  164. 'Wrapper for Server.HTMLEncode() -- makes it easier on the eyes when reading the HTML code
  165. Function H(s)
  166. If Not IsEmpty(s) and Not IsNull(s) then
  167. H = Server.HTMLEncode(s)
  168. Else
  169. H = ""
  170. End If
  171. End Function
  172. '------------------------------------------------------------------------------
  173. ' Canonical application URL helpers
  174. ' - Categories use numeric IDs
  175. ' - Posts use slug permalinks for public links and numeric IDs for admin actions
  176. '------------------------------------------------------------------------------
  177. Function CategoryUrl(ByVal categoryId)
  178. CategoryUrl = "/categories/" & Server.URLEncode(CStr(categoryId))
  179. End Function
  180. Function CategoriesUrl()
  181. CategoriesUrl = "/categories"
  182. End Function
  183. Function CategoryNewUrl()
  184. CategoryNewUrl = "/categories/new"
  185. End Function
  186. Function CategoryEditUrl(ByVal categoryId)
  187. CategoryEditUrl = CategoryUrl(categoryId) & "/edit"
  188. End Function
  189. Function CategoryDeleteUrl(ByVal categoryId)
  190. CategoryDeleteUrl = CategoryUrl(categoryId) & "/delete"
  191. End Function
  192. Function PostUrl(ByVal slug)
  193. PostUrl = "/posts/" & Server.URLEncode(CStr(slug))
  194. End Function
  195. Function PostsUrl()
  196. PostsUrl = "/posts"
  197. End Function
  198. Function PostNewUrl()
  199. PostNewUrl = "/posts/new"
  200. End Function
  201. Function PostEditUrl(ByVal postId)
  202. PostEditUrl = "/posts/" & Server.URLEncode(CStr(postId)) & "/edit"
  203. End Function
  204. Function PostDeleteUrl(ByVal postId)
  205. PostDeleteUrl = "/posts/" & Server.URLEncode(CStr(postId)) & "/delete"
  206. End Function
  207. Function AdminPostPublishUrl(ByVal postId)
  208. AdminPostPublishUrl = "/admin/posts/" & Server.URLEncode(CStr(postId)) & "/publish"
  209. End Function
  210. Function AdminPostUnpublishUrl(ByVal postId)
  211. AdminPostUnpublishUrl = "/admin/posts/" & Server.URLEncode(CStr(postId)) & "/unpublish"
  212. End Function
  213. Function AdminPostAIUrl(ByVal postId)
  214. AdminPostAIUrl = "/admin/posts/" & Server.URLEncode(CStr(postId)) & "/ai"
  215. End Function
  216. Function AdminUrl()
  217. AdminUrl = "/admin"
  218. End Function
  219. Function CommentsUrl()
  220. CommentsUrl = "/comments"
  221. End Function
  222. '=======================================================================================================================
  223. ' Adapted from Tolerable library
  224. '=======================================================================================================================
  225. ' This subroutine allows us to ignore the difference
  226. ' between object and primitive assignments. This is
  227. ' essential for many parts of the engine.
  228. Public Sub Assign(ByRef var, ByVal val)
  229. If IsObject(val) Then
  230. Set var = val
  231. Else
  232. var = val
  233. End If
  234. End Sub
  235. ' This is similar to the ? : operator of other languages.
  236. ' Unfortunately, both the if_true and if_false "branches"
  237. ' will be evalauted before the condition is even checked. So,
  238. ' you'll only want to use this for simple expressions.
  239. Public Function Choice(ByVal cond, ByVal if_true, ByVal if_false)
  240. If cond Then
  241. Assign Choice, if_true
  242. Else
  243. Assign Choice, if_false
  244. End If
  245. End Function
  246. ' Allows single-quotes to be used in place of double-quotes.
  247. ' Basically, this is a cheap trick that can make it easier
  248. ' to specify Lambdas.
  249. Public Function Q(ByVal input)
  250. Q = Replace(input, "'", """")
  251. End Function
  252. Function SurroundString(inputVar)
  253. If VarType(inputVar) = vbString Then
  254. SurroundString = """" & inputVar & """"
  255. Else
  256. SurroundString = inputVar
  257. End If
  258. End Function
  259. Function SurroundStringInArray(arr)
  260. Dim i
  261. For i = LBound(arr) To UBound(arr)
  262. If IsString(arr(i)) Then
  263. arr(i) = """" & arr(i) & """"
  264. End If
  265. Next
  266. SurroundStringInArray = arr
  267. End Function
  268. '-----------------------------------------------------------------------------------------------------------------------
  269. 'Boolean type checkers
  270. 'Don't forget IsArray is built-in!
  271. Function IsString(value)
  272. IsString = Choice(typename(value) = "String", true, false)
  273. End Function
  274. Function IsDict(value)
  275. IsDict = Choice(typename(value) = "Dictionary", true, false)
  276. End Function
  277. Function IsRecordset(value)
  278. IsRecordset = Choice(typename(value) = "Recordset", true, false)
  279. End Function
  280. Function IsLinkedList(value)
  281. IsLinkedList = Choice(typename(value) = "LinkedList_Class", true, false)
  282. End Function
  283. Function IsArray(value)
  284. IsArray = Choice(typename(value) = "Variant()", true, false)
  285. End Function
  286. '--------------------------------------------------------------------
  287. ' Returns True when the named key is present in Session.Contents
  288. ' • Handles scalars (String, Integer, etc.), objects, Empty, and Null
  289. '--------------------------------------------------------------------
  290. Function SessionHasKey(keyName)
  291. 'Loop over the existing keys—Session.Contents is like a dictionary
  292. Dim k
  293. For Each k In Session.Contents
  294. If StrComp(k, keyName, vbTextCompare) = 0 Then
  295. SessionHasKey = True
  296. Exit Function
  297. End If
  298. Next
  299. SessionHasKey = False 'not found
  300. End Function
  301. Function RenderObjectsAsTable(arr,boolUseTabulator)
  302. Dim html, propNames, i, j, obj, val, pkName, isPk
  303. If IsEmpty(arr) Or Not IsArray(arr) Then
  304. RenderObjectsAsTable = "<!-- no data -->"
  305. Exit Function
  306. End If
  307. Set obj = arr(0)
  308. On Error Resume Next
  309. propNames = obj.Properties
  310. pkName = obj.PrimaryKey
  311. On Error GoTo 0
  312. If IsEmpty(propNames) Or Len(pkName) = 0 Then
  313. RenderObjectsAsTable = "<!-- missing properties or primary key -->"
  314. Exit Function
  315. End If
  316. html = "<div class='table-wrapper'>" & vbCrLf
  317. html = html & "<table class='pobo-table' id='pobo-table'>" & vbCrLf
  318. html = html & " <thead><tr>" & vbCrLf
  319. For i = 0 To UBound(propNames)
  320. html = html & " <th>" & Server.HTMLEncode(propNames(i)) & "</th>" & vbCrLf
  321. Next
  322. html = html & " </tr></thead>" & vbCrLf
  323. html = html & " <tbody>" & vbCrLf
  324. For j = 0 To UBound(arr)
  325. Set obj = arr(j)
  326. html = html & " <tr>" & vbCrLf
  327. For i = 0 To UBound(propNames)
  328. val = GetDynamicProperty(obj, propNames(i))
  329. isPk = (StrComp(propNames(i), pkName, vbTextCompare) = 0)
  330. If IsNull(val) Or IsEmpty(val) Then
  331. val = "&nbsp;"
  332. ElseIf IsDate(val) Then
  333. val = FormatDateTime(val, vbShortDate)
  334. ElseIf VarType(val) = vbBoolean Then
  335. val = IIf(val, "True", "False")
  336. Else
  337. val = CStr(val)
  338. Dim maxLen : maxLen = CInt(GetAppSetting("TableCellMaxLength"))
  339. If maxLen <= 0 Then maxLen = 90
  340. If Len(val) > maxLen Then
  341. val = Left(val, maxLen - 3) & "..."
  342. End If
  343. val = Server.HTMLEncode(val)
  344. End If
  345. If isPk and boolUseTabulator = False Then
  346. val = "<a href=""" & obj.Tablename & "/edit/" & GetDynamicProperty(obj, pkName) & """ class=""table-link"">" & val & "</a>"
  347. End If
  348. html = html & " <td>" & val & "</td>" & vbCrLf
  349. Next
  350. html = html & " </tr>" & vbCrLf
  351. Next
  352. html = html & " </tbody>" & vbCrLf & "</table>" & vbCrLf & "</div>"
  353. RenderObjectsAsTable = html
  354. End Function
  355. Function RenderFormFromObject(obj)
  356. Dim html, propNames, i, name, val, inputType
  357. Dim pkName, tableName, checkedAttr
  358. On Error Resume Next
  359. propNames = obj.Properties
  360. pkName = obj.PrimaryKey
  361. tableName = obj.TableName
  362. On Error GoTo 0
  363. If IsEmpty(propNames) Or Len(pkName) = 0 Then
  364. RenderFormFromObject = "<!-- Invalid object -->"
  365. Exit Function
  366. End If
  367. html = "<form method='post' action='/" & tableName & "/save' class='article-content'>" & vbCrLf
  368. For i = 0 To UBound(propNames)
  369. name = propNames(i)
  370. val = GetDynamicProperty(obj, name)
  371. ' Handle nulls
  372. If IsNull(val) Then val = ""
  373. ' Primary key → hidden input
  374. If StrComp(name, pkName, vbTextCompare) = 0 Then
  375. html = html & " <input type='hidden' name='" & name & "' value='" & Server.HTMLEncode(val) & "' />" & vbCrLf
  376. 'Continue For
  377. End If
  378. html = html & " <div class='form-group'>" & vbCrLf
  379. html = html & " <label for='" & name & "'>" & name & "</label>" & vbCrLf
  380. Select Case True
  381. Case VarType(val) = vbBoolean
  382. checkedAttr = ""
  383. If val = True Then checkedAttr = " checked"
  384. html = html & " <input type='checkbox' class='form-check-input' name='" & name & "' id='" & name & "' value='true'" & checkedAttr & " />" & vbCrLf
  385. Case IsDate(val)
  386. html = html & " <input type='date' class='form-control' name='" & name & "' id='" & name & "' value='" & FormatDateForInput(val) & "' />" & vbCrLf
  387. Case IsNumeric(val)
  388. html = html & " <input type='number' class='form-control' name='" & name & "' id='" & name & "' value='" & val & "' />" & vbCrLf
  389. Case Len(val) > CInt(GetAppSetting("FormTextareaThreshold"))
  390. html = html & " <textarea class='form-control' name='" & name & "' id='" & name & "' rows='6'>" & Server.HTMLEncode(val) & "</textarea>" & vbCrLf
  391. Case Else
  392. html = html & " <input type='text' class='form-control' name='" & name & "' id='" & name & "' value='" & Server.HTMLEncode(val) & "' />" & vbCrLf
  393. End Select
  394. html = html & " </div>" & vbCrLf
  395. Next
  396. html = html & " <button type='submit' class='btn btn-primary btn-lg'>Save</button>" & vbCrLf
  397. html = html & "</form>" & vbCrLf
  398. RenderFormFromObject = html
  399. End Function
  400. Function GetDynamicProperty(obj, propName)
  401. On Error Resume Next
  402. Dim result
  403. Execute "result = obj." & propName
  404. If Err.Number <> 0 Then
  405. result = ""
  406. Err.Clear
  407. End If
  408. GetDynamicProperty = result
  409. On Error GoTo 0
  410. End Function
  411. Function FormatDateForInput(val)
  412. If IsDate(val) Then
  413. Dim yyyy, mm, dd
  414. yyyy = Year(val)
  415. mm = Right("0" & Month(val), 2)
  416. dd = Right("0" & Day(val), 2)
  417. FormatDateForInput = yyyy & "-" & mm & "-" & dd
  418. Else
  419. FormatDateForInput = ""
  420. End If
  421. End Function
  422. '-------------------------------------------------------------
  423. ' Returns obj.<propName> for any public VBScript class property
  424. '-------------------------------------------------------------
  425. Function GetObjProp(o, pName)
  426. Dim tmp
  427. ' Build a tiny statement like: tmp = o.UserID
  428. Execute "tmp = o." & pName
  429. GetObjProp = tmp
  430. End Function
  431. Function GenerateSlug(title)
  432. Dim slug
  433. slug = LCase(title) ' Convert to lowercase
  434. slug = Replace(slug, "&", "and") ' Replace ampersands
  435. slug = Replace(slug, "'", "") ' Remove apostrophes
  436. slug = Replace(slug, """", "") ' Remove quotes
  437. slug = Replace(slug, "–", "-") ' Replace en dash
  438. slug = Replace(slug, "—", "-") ' Replace em dash
  439. slug = Replace(slug, "/", "-") ' Replace slashes
  440. slug = Replace(slug, "\", "-") ' Replace backslashes
  441. ' Remove all non-alphanumeric and non-hyphen/space characters
  442. Dim i, ch, clean
  443. clean = ""
  444. For i = 1 To Len(slug)
  445. ch = Mid(slug, i, 1)
  446. If (ch >= "a" And ch <= "z") Or (ch >= "0" And ch <= "9") Or ch = " " Or ch = "-" Then
  447. clean = clean & ch
  448. End If
  449. Next
  450. ' Replace multiple spaces or hyphens with single hyphen
  451. Do While InStr(clean, " ") > 0
  452. clean = Replace(clean, " ", " ")
  453. Loop
  454. clean = Replace(clean, " ", "-")
  455. Do While InStr(clean, "--") > 0
  456. clean = Replace(clean, "--", "-")
  457. Loop
  458. ' Trim leading/trailing hyphens
  459. Do While Left(clean, 1) = "-"
  460. clean = Mid(clean, 2)
  461. Loop
  462. Do While Right(clean, 1) = "-"
  463. clean = Left(clean, Len(clean) - 1)
  464. Loop
  465. GenerateSlug = clean
  466. End Function
  467. Function GetRawJsonFromRequest()
  468. Dim stream, rawJson
  469. Set stream = Server.CreateObject("ADODB.Stream")
  470. stream.Type = 1 ' adTypeBinary
  471. stream.Open
  472. stream.Write Request.BinaryRead(Request.TotalBytes)
  473. stream.Position = 0
  474. stream.Type = 2 ' adTypeText
  475. stream.Charset = "utf-8"
  476. rawJson = stream.ReadText
  477. stream.Close
  478. Set stream = Nothing
  479. GetRawJsonFromRequest = rawJson
  480. End Function
  481. Function Active(controllerName)
  482. On Error Resume Next
  483. If Replace(Lcase(router.Resolve(Request.ServerVariables("REQUEST_METHOD"), TrimQueryParams(Request.ServerVariables("HTTP_X_ORIGINAL_URL")))(0)),"controller","") = LCase(controllerName) Then
  484. Active = "active"
  485. Else
  486. Active = ""
  487. End If
  488. On Error GoTo 0
  489. End Function
  490. '====================================================================
  491. ' FormatDateForSql
  492. ' Converts a VBScript Date to a SQL Server-compatible string
  493. ' Output: 'YYYY-MM-DD HH:MM:SS'
  494. '====================================================================
  495. Function FormatDateForSql(vbDate)
  496. If IsNull(vbDate) Or vbDate = "" Then
  497. FormatDateForSql = "NULL"
  498. Exit Function
  499. End If
  500. ' Ensure vbDate is a valid date
  501. If Not IsDate(vbDate) Then
  502. Err.Raise vbObjectError + 1000, "FormatDateForSql", "Invalid date: " & vbDate
  503. End If
  504. Dim yyyy, mm, dd, hh, nn, ss
  505. yyyy = Year(vbDate)
  506. mm = Right("0" & Month(vbDate), 2)
  507. dd = Right("0" & Day(vbDate), 2)
  508. hh = Right("0" & Hour(vbDate), 2)
  509. nn = Right("0" & Minute(vbDate), 2)
  510. ss = Right("0" & Second(vbDate), 2)
  511. ' Construct SQL Server datetime literal
  512. FormatDateForSql = "'" & yyyy & "-" & mm & "-" & dd & " " & hh & ":" & nn & ":" & ss & "'"
  513. End Function
  514. %>

Powered by TurnKey Linux.