Consolidated ASP Classic MVC framework from best components
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

571 lignes
19KB

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

Powered by TurnKey Linux.