├── .htaccess ├── README.md ├── Rockets-config.lisp ├── Rockets-navigation.lisp ├── docs ├── _config.yml ├── customizing_rockets_blog.md ├── extending_rockets.md ├── how_rockets_works.md ├── images │ ├── deleteme.txt │ └── newlisp-rockets-picture-small.jpg ├── index.md ├── install_rockets_linode.md ├── install_rockets_ubuntu.md ├── running_rockets_blog.md └── test.md ├── fileupload.lsp ├── images ├── eniac4.gif ├── forum-notice.png ├── nav-button-first.jpg ├── nav-button-last.jpg ├── nav-button-next.jpg ├── nav-button-prev.jpg ├── newlisp-rockets-picture-small.jpg ├── newlisp-rockets-picture.jpg ├── poweredby.png ├── read-msg.png ├── rockets.png ├── rockets │ ├── r111.jpg │ ├── r11332.jpg │ ├── r1156.jpg │ ├── r12994.jpg │ ├── r13174.jpg │ ├── r13519.jpg │ ├── r14351.jpg │ ├── r15537.jpg │ ├── r15718.jpg │ ├── r17449.jpg │ ├── r18260.jpg │ ├── r18459.jpg │ ├── r18710.jpg │ ├── r19993.jpg │ ├── r20296.jpg │ ├── r20803.jpg │ ├── r22615.jpg │ ├── r24597.jpg │ ├── r24873.jpg │ ├── r24941.jpg │ ├── r25049.jpg │ ├── r25098.jpg │ ├── r25227.jpg │ ├── r25721.jpg │ ├── r26593.jpg │ ├── r30618.jpg │ ├── r30790.jpg │ ├── r31383.jpg │ ├── r31961.jpg │ ├── r33735.jpg │ ├── r33942.jpg │ ├── r34429.jpg │ ├── r34540.jpg │ ├── r3458.jpg │ ├── r36340.jpg │ ├── r37682.jpg │ ├── r37709.jpg │ ├── r39914.jpg │ ├── r40190.jpg │ ├── r41090.jpg │ ├── r41567.jpg │ ├── r42568.jpg │ ├── r43159.jpg │ ├── r45026.jpg │ ├── r46066.jpg │ ├── r46414.jpg │ ├── r46949.jpg │ ├── r47432.jpg │ ├── r47476.jpg │ ├── r49325.jpg │ ├── r4952.jpg │ ├── r49658.jpg │ ├── r51955.jpg │ ├── r54205.jpg │ ├── r54539.jpg │ ├── r54642.jpg │ ├── r59211.jpg │ ├── r59377.jpg │ ├── r63177.jpg │ ├── r6520.jpg │ ├── r65409.jpg │ ├── r65528.jpg │ ├── r65697.jpg │ ├── r66502.jpg │ ├── r66566.jpg │ ├── r70179.jpg │ ├── r71140.jpg │ ├── r71294.jpg │ ├── r71940.jpg │ ├── r72074.jpg │ ├── r72466.jpg │ ├── r73358.jpg │ ├── r73623.jpg │ ├── r74531.jpg │ ├── r75534.jpg │ ├── r75775.jpg │ ├── r84391.jpg │ ├── r84654.jpg │ ├── r85098.jpg │ ├── r85249.jpg │ ├── r8567.jpg │ ├── r86353.jpg │ ├── r87629.jpg │ ├── r88269.jpg │ ├── r88708.jpg │ ├── r88882.jpg │ ├── r90879.jpg │ ├── r91551.jpg │ ├── r93755.jpg │ ├── r93847.jpg │ ├── r94150.jpg │ ├── r94993.jpg │ ├── r95397.jpg │ ├── r97400.jpg │ ├── r9749.jpg │ ├── r97516.jpg │ ├── r97531.jpg │ ├── r98299.jpg │ ├── r98632.jpg │ └── r99291.jpg ├── rss.png └── unread-msg.png ├── index.cgi ├── log-to-database.lisp ├── newlisp-rockets.lisp ├── partials ├── panel1.html ├── panel2.html ├── panel3.html ├── panel4.html ├── rockets-checksignin.lsp ├── rockets-common-functions.lsp ├── rockets-custom.lsp ├── rockets-generate-rss.lsp ├── rockets-leftpanel.lsp ├── rockets-navbar.lsp ├── rockets-panel1.lsp ├── rockets-panel2.lsp ├── rockets-panel3.lsp ├── rockets-panel4.lsp ├── rockets-rightpanel.lsp └── rockets-sidepanels.lsp ├── podcast └── readme.txt ├── revision-history.txt ├── rocket-list.lisp ├── rockets-404.lsp ├── rockets-about.lsp ├── rockets-admin.lsp ├── rockets-adminupload.lsp ├── rockets-avatarupload.lsp ├── rockets-comic.lsp ├── rockets-comment-post.lsp ├── rockets-delete-confirm.lsp ├── rockets-delete.lsp ├── rockets-documentation.lsp ├── rockets-edit-post.lsp ├── rockets-experimental.lsp ├── rockets-forgotpassword.lsp ├── rockets-forum.lsp ├── rockets-item.lsp ├── rockets-main.lsp ├── rockets-poll.lsp ├── rockets-post.lsp ├── rockets-profile.lsp ├── rockets-register-confirm.lsp ├── rockets-register.lsp ├── rockets-signout.lsp ├── rockets-verify.lsp ├── rockets-why.lsp ├── setup-rockets.lisp └── upgrade.lisp /.htaccess: -------------------------------------------------------------------------------- 1 | AddDefaultCharset UTF-8 2 | Options -Indexes +FollowSymLinks 3 | 4 | # Prevent database backup files from being accessed 5 | 6 | Order allow,deny 7 | Deny from all 8 | 9 | 10 | # Prevent database files from being accessed 11 | 12 | Order allow,deny 13 | Deny from all 14 | 15 | 16 | # Prevent framework source from being accessed 17 | 18 | Order allow,deny 19 | Deny from all 20 | 21 | 22 | # 404 document page 23 | ErrorDocument 404 /rockets-404.lsp 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | newLISP-on-Rockets 2.0 2 | ====================== 3 | 4 | ![Rockets Logo](images/newlisp-rockets-picture-small.jpg) 5 | 6 | newLISP on Rockets is a fast, fun, and customizable blog application that is open source. It runs on the Linux platform. 7 | 8 | Rockets is written by [Jeremy Reimer](https://jeremyreimer.com). 9 | 10 | Read the documentation here: https://newlisponrockets.github.io/newLISP-on-Rockets/ 11 | 12 | This repo contains the source code for both the newLISP on Rockets framework and a blog that runs on Rockets. 13 | 14 | Please check the [Rockets blog](https://newlisponrockets.com) for updates on the status of the project. 15 | 16 | DISCLAIMER: In no way should this software be used to control actual rockets. 17 | 18 | What is newLISP-on-Rockets? 19 | --------------------------- 20 | 21 | Rockets started as a very simple web application framework running on newLISP. My goal was to simplify the web applications I was already writing in newLISP by consolidating a bunch of useful functions for both front-end (jQuery) and back-end (SQLite) operations. The emphasis was on simplicity and code conciseness. 22 | 23 | Over time, I've adapted Rockets for use as my own personal blog, as well as other web projects I'm working on. This meant that the development framework and the blog have merged into a simple yet easily extensible blog application. 24 | 25 | Documentation is available at: https://newlisponrockets.github.io/newLISP-on-Rockets/ 26 | 27 | You can view how the blog looks in a live environment by visiting: https://newlisponrockets.com 28 | 29 | Rockets 3.0 development 30 | ----------------------- 31 | 32 | Currently I'm working on a very experimental 3.0 version of Rockets, that adds HTML5 Canvas support. 33 | 34 | More info about this soon! 35 | 36 | 37 | -------------------------------------------------------------------------------- /Rockets-config.lisp: -------------------------------------------------------------------------------- 1 | 2 | (context 'RocketsConfig) 3 | 4 | (set 'AdminEmail "newlisponrockets@newlisponrockets.com") 5 | 6 | (set 'Database "ROCKETS-BLOG") 7 | 8 | (set 'FrontPageType 2) 9 | 10 | (set 'HeaderImage "newlisp-rockets-2-logo.jpg") 11 | 12 | (set 'IndividualPageType 1) 13 | 14 | (set 'LeftPanel '("box1" "popposts" "recentposts" "blogtopics")) 15 | 16 | (set 'Name "The newLISP on Rockets 2.0 Blog") 17 | 18 | (set 'Owner "Rocket Man") 19 | 20 | (set 'ShortName "newLISP on Rockets") 21 | 22 | (set 'SiteURL "newlisponrockets.com") 23 | 24 | 25 | (context MAIN) 26 | 27 | -------------------------------------------------------------------------------- /Rockets-navigation.lisp: -------------------------------------------------------------------------------- 1 | 2 | (context 'RocketsNavigation) 3 | 4 | (set 'navbar-list '( 5 | ("About" "rockets-about") 6 | ("Docs" "rockets-documentation") 7 | ("Forum" "rockets-forum") 8 | ("Why Rockets?" "rockets-why") 9 | ("Download" "rockets-item.lsp?p=127"))) 10 | 11 | 12 | (context MAIN) 13 | 14 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /docs/customizing_rockets_blog.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Rockets 2.0 Documentation - Customizing your Rockets Blog 4 | --- 5 | 6 | [Back to the main page](index.md) 7 | 8 | # Customizing your Rockets Blog 9 | 10 | To customize your Rockets blog, you must log in as the Admin user. See [Running your Rockets blog](running_rockets_blog) for details. 11 | 12 | ## Go to the Admin page 13 | 14 | Once you have signed in as the Admin user, click your user name at the upper right of the top menu, then click "Admin page" from the dropdown menu. 15 | 16 | The Admin page contains five sub-pages, identified by blue buttons/tabs on the top of the page. These include: 17 | 18 | * General Configuration 19 | * Custom Configuration 20 | * Media Configuration 21 | * User Configuration 22 | * Podcast Configuration 23 | 24 | ## General Configuration 25 | 26 | Here you can set custom images for your blog header and forum header, change the name of your blog, customize the top menu, and configure page layouts. 27 | 28 | ### Changing blog and header images 29 | 30 | To change blog and header forum images, click "Choose File", select a file from your computer and click OK, then click "Upload". 31 | 32 | **WARNING: There is no file size limit in this dialog box. Try to choose image files 800 x 600 pixels or smaller.** 33 | 34 | ### Customizing the menu 35 | 36 | To customize the top menu, enter in the menu name and target page name in the box. You can also delete menu items individually, or add new blank ones. 37 | 38 | **NOTE: The page name doesn't have to include the ".lsp" extension, unless it is a numbered page, such as "rockets-item.lsp?p=127"** 39 | 40 | ### Changing page layouts 41 | 42 | You can change these layouts at any time. 43 | 44 | The options for the Main Page layout are: 45 | 46 | * Single page with custom content 47 | * Single plage with blog posts (the default) 48 | * Two columns with custom left hand navbar content 49 | * Three columns with custom left and right hand navbar content 50 | 51 | I like to have my main page set to a three-column layout, since that allows for all sorts of cool ways to promote other projects on your main page. 52 | 53 | NOTE: If you choose "Single page with custom content", that custom content must be programmed by you. See [Extending Rockets](extending_rockets.md) for more information. 54 | 55 | The options for individual page layout are: 56 | 57 | * Imdividual post by itself 58 | * Two columns with custom left hand navbar content 59 | * Three columns with custom left and right hand navbar content 60 | 61 | Below these options, you can select the custom content for the left and right hand navbars (columns). 62 | 63 | The content options are: 64 | 65 | * Custom HTML display box 1 66 | * Most popular blog posts 67 | * Recent forum posts 68 | * Forum link 69 | * Custom HTML display box 2 70 | * Custom HTML display box 3 71 | * Blog topics 72 | * Custom HTML display box 4 73 | 74 | You can select none, some, or all of these items, but you can't change their order. Yet. 75 | 76 | The "Custom HTML display box" can literally display any HTML that you want. This is really useful for things like newsletters that offer custom signup HTML panels. 77 | 78 | You edit these custom HTML display boxes by clicking the "Custom Configuration" tab at the top of the page (see below) 79 | 80 | ## Custom configuration 81 | 82 | These are the custom HTML display boxes described above. 83 | 84 | You can put any raw HTML you want in here, including HTML that contains Javascript (usually using the `") 43 | ) 44 | 45 | (define (save-state) 46 | (displayln " ctx.save();") 47 | ) 48 | 49 | (define (restore-state) 50 | (displayln " ctx.restore();") 51 | ) 52 | 53 | (define (clear-rect x y width height) 54 | (displayln " ctx.clearRect(" x ", " y ", " width ", " height ");") 55 | ) 56 | 57 | (define (req-anim-frame) 58 | (displayln " window.requestAnimationFrame(draw);") 59 | ) 60 | 61 | (define (draw-image imagename x y width height tiled) 62 | (setq imagenum (find imagename image-list 1)) 63 | (if tiled (begin 64 | (let ((numx (/ canvas-width width)) 65 | (numy (/ canvas-height height))) 66 | (displayln " for (let i = 0; i < " numy "; i++) {") 67 | (displayln " for (let j = 0; j < " numx "; j++) {") 68 | (displayln " ctx.drawImage(img" imagenum ", j * " width ", i * " height ", " width ", " height ");") 69 | (displayln " }") 70 | (displayln " };") 71 | )) 72 | (begin 73 | (display " ctx.drawImage(img" imagenum ", " x ", " y ) 74 | (if (or width height) (display ", " width ", " height)) 75 | (displayln ");") 76 | ) 77 | ) 78 | ) 79 | 80 | (define (draw-rectangle x y width height filled) 81 | (if filled 82 | (displayln " ctx.fillRect(" x ", " y ", " width ", " height ");") 83 | (displayln " ctx.strokeRect(" x ", " y ", " width ", " height ");") 84 | ) 85 | ) 86 | 87 | (define (draw-text x y text font size serif filled) 88 | (if filled 89 | (begin 90 | (displayln " ctx.font = \"" size "px " font "\";") 91 | (displayln " ctx.fillText(\"" text "\", " x ", " y ");") 92 | ) 93 | (begin 94 | (displayln " ctx.font = \"" size "px " font "\";") 95 | (displayln " ctx.strokeText(\"" text "\", " x ", " y ");") 96 | ) 97 | ) 98 | ) 99 | 100 | (load "Rockets-config.lisp") ; load configuration information 101 | (display-header) 102 | (open-database RocketsConfig:Database) 103 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 104 | 105 | (display-partial "rockets-navbar") 106 | 107 | (start-div "hero-unit") 108 | (displayln "

Experimental Rockets 3.0 Test page

") 109 | (displayln "

Please proceed with caution!

") 110 | (end-div) 111 | 112 | ;(displayln "

Debug stuff here...

") 113 | ; this stuff is subject to change! 114 | 115 | (setq imagenum 0) 116 | 117 | (setq canvas-width 800) 118 | (setq canvas-height 600) 119 | (setq canvas-id "test1") 120 | (setq image-list '( 121 | "images/sun_halloween.jpg" 122 | "images/poweredby.png" 123 | "images/16pxdither3.png" 124 | )) 125 | (init-canvas canvas-id canvas-width canvas-height image-list) 126 | (clear-rect 0 0 canvas-width canvas-height) 127 | (draw-image "16pxdither3" 0 0 16 16 true) 128 | (draw-rectangle 25 25 300 100) 129 | (draw-text 50 75 "Hello, World!" "serif" 48 true true) 130 | (draw-image "poweredby" 50 175 200 200) 131 | (req-anim-frame) 132 | (draw-image "poweredby" 150 175) 133 | (draw-image "sun_halloween" 50 275 400 400) 134 | (close-canvas) 135 | 136 | (displayln "

STUFF GOES HERE...

") 137 | 138 | (close-database) 139 | (display-footer RocketsConfig:Owner) 140 | (display-page) ; this is needed to actually display the page! 141 | -------------------------------------------------------------------------------- /rockets-forgotpassword.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-forgotpassword.lsp) - Rockets - Forgot password page 6 | ; 7 | 8 | (load "Rockets-config.lisp") ; load configuration information 9 | (module "crypto.lsp") ; for setting new passwords 10 | (display-header (string RocketsConfig:Name " - Forgot Password")) 11 | (open-database RocketsConfig:Database) 12 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 13 | (display-partial "rockets-navbar") 14 | (display-partial "rockets-common-functions") 15 | 16 | (start-div "hero-unit") 17 | (displayln "

Forgot Password

") 18 | ;(displayln "

Currently running newLISP on Rockets version: " $ROCKETS_VERSION "

") 19 | ;(displayln "

Writing Holmes is an experimental writing site. Feel free to look around!

") 20 | (end-div) 21 | 22 | (define (expire-old-tokens) 23 | (dolist (x RocketsTokens:Tokens) 24 | ;(displayln "
" (x 0)) 25 | (if (< (- (date-value) (x 0)) (* 60 60)) 26 | (push x remaining-tokens -1) 27 | ;(displayln " over an hour minute old") 28 | ) 29 | ) 30 | (set 'RocketsTokens:Tokens remaining-tokens) 31 | ;(displayln "

New list: " RocketsTokens:Tokens) 32 | ) 33 | 34 | ; start executing page----------------------- 35 | 36 | (if (nil? RocketsConfig:AdminEmail) 37 | (set 'RocketsConfig:AdminEmail "newlisponrockets@newlisponrockets.com")) 38 | 39 | (if (nil? RocketsConfig:SiteURL) 40 | (set 'RocketsConfig:SiteURL "pleaseconfigureyoursiteurl.com")) 41 | 42 | (set 'email-to-send ($POST "email")) 43 | 44 | (set 'uuid-to-verify ($GET "u")) 45 | 46 | (if (file-info "reset-tokens.lisp") (load "reset-tokens.lisp")) 47 | 48 | (if uuid-to-verify (begin 49 | (set 'uuid-expired-message (string "

You have attempted to reset your password, but the one-hour reset window has expired. Please return to the Forgot Password page and try again.")) 50 | ; first verify that uuid exists 51 | (if RocketsTokens:Tokens 52 | (begin 53 | ;(displayln "

Token file exists") 54 | (expire-old-tokens) 55 | (save "reset-tokens.lisp" 'RocketsTokens) 56 | ;(displayln "

new tokens: " RocketsTokens:Tokens) 57 | (if (and RocketsTokens:Tokens (ref uuid-to-verify RocketsTokens:Tokens)) 58 | (begin 59 | (set 'new-password ($POST "pass")) 60 | (set 'confirm-password ($POST "conf")) 61 | (displayln "

Reset your password

") 62 | (displayln "

") 63 | (displayln "

Enter new password:   ") 64 | (displayln "

Type again to confirm: ") 65 | (if (and new-password (= (trim new-password) "")) 66 | (display-error "You must enter a password")) 67 | (if (and new-password (!= new-password confirm-password)) 68 | (display-error "Passwords do not match.")) 69 | (displayln "") 70 | (displayln "

") 71 | (if (and new-password (= new-password confirm-password)) (begin 72 | (displayln "

Passwords match! Now changing and logging you in.") 73 | ; first find the appropriate email address 74 | (set 'ref-uuid (ref uuid-to-verify RocketsTokens:Tokens)) 75 | (if ref-uuid (set 'email-to-reset (RocketsTokens:Tokens (first ref-uuid) 2))) 76 | (displayln "

email to change: " email-to-reset) 77 | (set 'UserEmail email-to-reset) 78 | (if UserEmail (set 'user-data (first (get-record "Users" UserEmail)))) 79 | (displayln "

User data: " user-data) 80 | (if user-data (begin 81 | (set 'UserSalt (user-data 3)) 82 | (set 'CookieSalt (user-data 8)) 83 | (set 'UserPasswordHash (crypto:sha1 (string UserSalt new-password))) 84 | ;(displayln "

New password: " UserPasswordHash) 85 | (update-record "Users" UserEmail UserPasswordHash) 86 | (displayln "

Password updated!") 87 | ; now set the cookie 88 | (set 'UserId (user-data 0)) 89 | (set 'new-cookie (string UserId "|" CookieSalt)) 90 | (set-cookie Blog:rocket-cookie-name new-cookie (date-value 2053 2 28)) 91 | (page-redirect "rockets-main" "e=resetpassword") 92 | )) 93 | )) 94 | ) 95 | (displayln uuid-expired-message) 96 | ) 97 | ) 98 | (displayln uuid-expired-message) 99 | ) 100 | )) 101 | 102 | (if email-to-send (begin 103 | (set 'date-of-email (date-value)) 104 | (set 'uuid-of-email (uuid)) 105 | (push (list date-of-email uuid-of-email email-to-send) RocketsTokens:Tokens -1) 106 | (expire-old-tokens) 107 | (save "reset-tokens.lisp" 'RocketsTokens) 108 | (set 'link-text (string "http://" RocketsConfig:SiteURL "/rockets-forgotpassword.lsp?u=" uuid-of-email )) 109 | (set 'email-text (string "Either you, or someone pretending to be you, has sent a Reset Password request for the site " RocketsConfig:Name ". To reset your password, click on this link: " link-text ". If you did not request a password reset, please ignore this message.")) 110 | (set 'subject-text (string "Reset password request for " RocketsConfig:Name)) 111 | ; check if it was a valid email address 112 | (set 'check-if-valid-email (query (string "SELECT * From Users WHERE UserEmail='" email-to-send "';"))) 113 | (if check-if-valid-email 114 | (begin 115 | (displayln "

We are sending a message to your email address. If you don't receive it right away, check your Spam folder. Click on the link in the email to reset your password.") 116 | (send-mail email-to-send RocketsConfig:AdminEmail RocketsConfig:Owner subject-text email-text) 117 | ) 118 | (displayln "

Sorry, that email address was not found in our user database. Try again.") 119 | ) 120 | ;(displayln "

Sending email to: " email-to-send " from " RocketsConfig:AdminEmail " on " date-of-email " code: " uuid-of-email) 121 | 122 | ) 123 | (if (not uuid-to-verify) (begin 124 | (displayln "

") 125 | (displayln "

Email address: ") 126 | (displayln "") 127 | )) 128 | ) 129 | 130 | (close-database) 131 | (display-footer RocketsConfig:Owner) 132 | (display-page) ; this is needed to actually display the page! 133 | -------------------------------------------------------------------------------- /rockets-forum.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; Rockets-forum.lsp - Rockets forum page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header (string RocketsConfig:Name " - Forum")) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (display-partial "rockets-common-functions") ; loads functions common to the blog but not part of Rockets 17 | (set 'active-page "rockets-forum") 18 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 19 | 20 | (start-div "hero-unit") 21 | (if RocketsConfig:DiscussionImage 22 | (display-image RocketsConfig:DiscussionImage) 23 | (display-image "newlisp-rockets-picture-small" 480 270) 24 | ) 25 | (displayln "

The " RocketsConfig:ShortName " Discussion Forum

") 26 | (if RocketsConfig:ForumSubtitle (displayln "

" RocketsConfig:ForumSubtitle "

")) 27 | (end-div) 28 | 29 | ; If user has selected "Mark All As Read" then, well, mark all as read! 30 | (set 'mark-all ($GET "markall")) 31 | (if (and mark-all Rockets:UserId) (begin ; but you have to be logged in of course 32 | (set 'all-posts (query "SELECT Id from Posts")) ; put all posts ids into a list 33 | (set 'read-posts-line "") 34 | (dolist (r all-posts) (extend read-posts-line (string (first r) "-"))) 35 | (set 'UserId Rockets:UserId) 36 | (set 'UserReadPosts read-posts-line) 37 | (update-record "Users" UserId UserReadPosts) 38 | (page-redirect "rockets-forum") ; we have to do a redirect to refresh the page 39 | )) 40 | 41 | ; get current page from URL (if there is one) 42 | (set 'current-page (force-parameters 1 ($GET "p"))) ; we only need the first part, ignore anything else 43 | (if current-page (set 'current-page (int current-page)) (set 'current-page 1)) 44 | 45 | ; get all existing posts 46 | (set 'total-posts (int (first (first (query (string "SELECT Count(*) FROM Posts")))))) 47 | 48 | (set 'total-pages (/ total-posts Blog:forum-posts-per-page)) 49 | (if (>= (mod (float total-posts) (float Blog:forum-posts-per-page)) 1) (inc total-pages)) ; fix number of pages if not evenly divisible 50 | 51 | (display-paging-links 1 total-pages current-page active-page) 52 | 53 | (set 'start-post-num (- (* current-page Blog:forum-posts-per-page) Blog:forum-posts-per-page)) 54 | ; get all Forum Notices 55 | (set 'posts-query-notices-sql (string "SELECT * from Posts WHERE PostType='Forum notice' ORDER BY PostLastDate DESC;")) 56 | ; get all posts of all types EXCEPT Forum Notices 57 | (set 'posts-query-sql (string "SELECT * from Posts WHERE PostType!='Forum notice' ORDER BY PostLastDate DESC LIMIT " start-post-num "," Blog:forum-posts-per-page ";")) 58 | 59 | (set 'posts-result-notices (query posts-query-notices-sql)) 60 | (set 'posts-result (query posts-query-sql)) 61 | (if posts-result-notices (set 'posts-result (append posts-result-notices posts-result))) 62 | 63 | ; print out all posts 64 | (dolist (x posts-result) 65 | (set 'post-num (x 0)) 66 | (set 'post-author (author-name (x 1))) 67 | (set 'post-avatar (author-avatar (x 1))) 68 | (set 'post-date (x 2)) 69 | (set 'post-subject (x 3)) 70 | (set 'post-content (x 4)) 71 | (set 'post-replies (x 5)) (if (nil? post-replies) (set 'post-replies "0")) 72 | (set 'post-type (x 6)) 73 | (set 'post-views (x 7)) 74 | (set 'post-lastauthor (x 10)) 75 | (set 'post-lastdate (x 11)) 76 | (if (nil? post-views) (set 'post-views 0)) ; needed because views was a late addition 77 | ; check to see if the user has read this post or not 78 | (if Rockets:UserReadPosts (begin 79 | (if (or (find (string post-num "-") Rockets:UserReadPosts) (nil? Rockets:UserId)) ; if you're not logged in OR if you are, and you've read the post 80 | (set 'post-read (string " ")) 81 | (set 'post-read (string " ")) 82 | )) 83 | (set 'post-read (string " ")) 84 | ) 85 | ; if the post is a forum notice, then make sure the icon is always an exclamation point 86 | (if (= post-type "Forum notice") (set 'post-read (string " "))) 87 | (push (list (string "

" post-read post-subject "

") 88 | (string "
" post-type "
") 89 | (string "
" post-author "
") 90 | (string "
" post-views " views / " post-replies " replies
") 91 | (string "
" post-lastdate " by " post-lastauthor "
")) forum-post-table -1) 92 | (push (list (string "rockets-item.lsp?p=" post-num "&f=true") nil nil nil (string "rockets-item.lsp?p=" post-num "&f=true#reply")) forum-links-table -1) 93 | ) 94 | 95 | (display-responsive '("Topic Subject" "Post Type" "Post Author" "Views / Replies" "Last Post") forum-post-table "striped" forum-links-table '(5 1 2 2 2)) 96 | 97 | (display-paging-links 1 total-pages current-page active-page) ; display them again 98 | 99 | ; add "Mark all posts as read" button 100 | (if Rockets:UserId 101 | (displayln "Mark all posts as read")) 102 | 103 | ; print post entry box 104 | (if Rockets:UserId (begin 105 | (display-post-box "Post something..." "postsomething" "rockets-post.lsp" "subjectline" "replybox" "Post Message" nil nil nil "Forum" true) 106 | )) ; any registered user may make a forum post 107 | 108 | (close-database) 109 | (display-footer RocketsConfig:Owner) 110 | (display-page) ; this is needed to actually display the page! 111 | 112 | -------------------------------------------------------------------------------- /rockets-item.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | (load "newlisp-rockets.lisp") 3 | (load "Rockets-config.lisp") ; load configuration information 4 | (display-header (string RocketsConfig:Name " - Post")) 5 | (open-database RocketsConfig:Database) 6 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 7 | (display-partial "rockets-common-functions") ; loads functions common to the blog but not part of Rockets 8 | (set 'active-page "rockets-item") 9 | (set 'Id (integer (force-parameters 1 ($GET "p")))) 10 | (set 'edit-post (force-parameters 1 ($GET "edit"))) 11 | (set 'forum-view-post (force-parameters 1 ($GET "f"))) 12 | (set 'edit-comment (force-parameters 1 ($GET "edit-comment"))) 13 | 14 | (if Id (extend active-page (string ".lsp?p=" Id))) ; in case user logs in and wants to return to this exact page 15 | (if forum-view-post (extend active-page (string "&f=true"))) 16 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 17 | 18 | (define (display-item) 19 | 20 | (if Id (begin 21 | (set 'post-content (get-record "Posts" Id)) 22 | (if post-content (begin 23 | (display-individual-post (first post-content) true Id) ; true= display comments, Id=link to page 24 | (if Rockets:UserId (begin ; check to see if user is signed in 25 | (if (not (find (string Id "-") Rockets:UserReadPosts)) ; check to see if post is not in user's read list 26 | (begin 27 | (push (string Id "-") Rockets:UserReadPosts -1) ; add it to read list 28 | (set 'UserId Rockets:UserId) ; get variables ready to write to database 29 | (set 'UserReadPosts Rockets:UserReadPosts) 30 | (update-record "Users" UserId UserReadPosts) 31 | )) 32 | ))) 33 | (displayln "

Sorry! We couldn't find that post.

")) 34 | ) 35 | (displayln "") ; we used to apologize for not showing a post, but if you're editing a comment you won't see it anyway. 36 | ) 37 | 38 | (if (and edit-post Rockets:IsUserAdmin) (begin ; only Admins can edit posts for now. 39 | (displayln "") 40 | (set 'post-content (first post-content)) 41 | (display-post-box "Edit post..." "postsomething" "rockets-edit-post" "subjectline" "replybox" "Update Message" Id (post-content 3) (post-content 4)) 42 | )) 43 | 44 | (if (and edit-comment Rockets:IsUserAdmin) (begin ; only Admins can edit comments for now. 45 | (set 'Id (force-parameters 1 ($GET "pid"))) 46 | (set 'comment-content (get-record "Comments" Id)) 47 | (displayln "") 48 | (set 'comment-content (first comment-content)) 49 | (display-post-box "Edit comment..." "commentsomething" "rockets-edit-post" "subjectline" "replybox" "Update Message" Id (comment-content 4) (comment-content 5) "comment") 50 | )) 51 | ) 52 | 53 | (case RocketsConfig:IndividualPageType 54 | (0 (display-item)) 55 | (1 (start-div "row-fluid") (start-div "span4") (display-partial "rockets-leftpanel") (end-div) 56 | (start-div "span8") (display-item) (end-div) (end-div) ) 57 | (2 (start-div "row-fluid") (start-div "span3") (display-partial "rockets-leftpanel") (end-div) 58 | (start-div "span6") (display-item) (end-div) 59 | (start-div "span3") (display-partial "rockets-rightpanel") (end-div) (end-div)) 60 | ) 61 | 62 | (display-footer RocketsConfig:Owner) 63 | (display-page) -------------------------------------------------------------------------------- /rockets-main.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; Rockets 2.0 - Main Page 6 | ; 7 | ; This is the second version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is minimalist but functional, and can be customized in the Admin control panel 9 | ; 10 | ; Copyright 2012-2018 by Jeremy Reimer (aka Rocket Man) 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header RocketsConfig:Name) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (display-partial "rockets-common-functions") ; loads functions common to the blog but not part of Rockets 17 | (set 'active-page "rockets-main") 18 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 19 | 20 | ; get current page from URL (if there is one) 21 | (set 'current-page (force-parameters 1 ($GET "p"))) ; we only need the first part, ignore anything else 22 | (if current-page (set 'current-page (int current-page)) (set 'current-page 1)) 23 | 24 | (define (display-hero-unit) 25 | (start-div "hero-unit") 26 | (if RocketsConfig:HeaderImage 27 | (display-image RocketsConfig:HeaderImage) 28 | (display-image "newlisp-rockets-picture.jpg" 960 540) 29 | ) 30 | (displayln "

" RocketsConfig:Name "

") 31 | (end-div) 32 | ; add an RSS feed link 33 | (displayln "

 RSS Feed for this blog

") 34 | ) 35 | 36 | (define (display-custom-content) 37 | (display-partial "rockets-custom") 38 | ) 39 | 40 | (define (display-blog-posts) 41 | ; admin anchor link for posting 42 | (if Rockets:IsUserAdmin (displayln "

Jump to post box

")) 43 | ; get optional limiting tag 44 | (set 'tag-name (force-parameters 1 ($GET "tags"))) 45 | (if tag-name (displayln "

Showing topics tagged as: " tag-name "

")) 46 | ; get all existing posts 47 | (if tag-name 48 | (set 'total-posts (int (first (first (query (string "SELECT Count(*) FROM Posts WHERE PostType='Blog post' AND PostTags LIKE '%" tag-name "%'")))))) 49 | (set 'total-posts (int (first (first (query (string "SELECT Count(*) FROM Posts WHERE PostType='Blog post' OR PostType='Podcast'")))))) 50 | ) 51 | (set 'total-pages (/ total-posts Blog:posts-per-page)) 52 | (if (>= (mod (float total-posts) (float Blog:posts-per-page)) 1) (inc total-pages)) ; fix number of pages if not evenly divisible 53 | 54 | (display-paging-links 1 total-pages current-page active-page) 55 | 56 | (set 'start-post-num (- (* current-page Blog:posts-per-page) Blog:posts-per-page)) 57 | (if tag-name 58 | (set 'posts-query-sql (string "SELECT * from Posts WHERE PostType='Blog post' AND PostTags LIKE '%" tag-name "%' ORDER BY Id DESC LIMIT " start-post-num "," Blog:posts-per-page ";")) 59 | (set 'posts-query-sql (string "SELECT * from Posts WHERE PostType='Blog post' OR PostType='Podcast' ORDER BY Id DESC LIMIT " start-post-num "," Blog:posts-per-page ";")) 60 | ) 61 | (set 'posts-result (query posts-query-sql)) 62 | ; print out all posts 63 | (dolist (x posts-result) 64 | (display-individual-post x) 65 | ) 66 | 67 | (display-paging-links 1 total-pages current-page active-page) ; display them again 68 | 69 | ; print post entry box 70 | (if Rockets:IsUserAdmin (begin 71 | (displayln "") ; anchor link for post box 72 | (display-post-box "Post something..." "postsomething" "rockets-post.lsp" "subjectline" "replybox" "Post Message" nil nil nil nil true "tags" '("Blog post" "Page" "Podcast" "Comic" "Forum notice")) 73 | )) ; only an administrator may make new blog posts 74 | ) 75 | 76 | (case RocketsConfig:FrontPageType 77 | (0 (display-custom-content)) 78 | (1 (display-hero-unit) (display-blog-posts)) 79 | (2 (display-hero-unit) (start-div "row-fluid") (start-div "span4") (display-partial "rockets-leftpanel") (end-div) 80 | (start-div "span8") (display-blog-posts) (end-div) (end-div) ) 81 | (3 (display-hero-unit) (start-div "row-fluid") (start-div "span3") (display-partial "rockets-leftpanel") (end-div) 82 | (start-div "span6") (display-blog-posts) (end-div) 83 | (start-div "span3") (display-partial "rockets-rightpanel") (end-div) (end-div)) 84 | ) 85 | 86 | (close-database) 87 | (display-footer RocketsConfig:Owner) 88 | (display-page) ; this is needed to actually display the page! 89 | 90 | -------------------------------------------------------------------------------- /rockets-poll.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; Rockets - Poll submission page rockets-poll.lsp 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header RocketsConfig:Name) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (display-partial "rockets-common-functions") ; loads functions common to the blog but not part of Rockets 17 | (set 'active-page "rockets-main") 18 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 19 | 20 | (if Rockets:UserId (begin ; must be signed in to vote 21 | 22 | ;(displayln "

Vote submitted!

") 23 | ;(displayln "

This feature isn't finished yet. Here is some debugging info:") 24 | ;(displayln "

Here is your POST data: " ($POST) ) 25 | (set 'PostSubject (first (first ($POST)))) 26 | (replace "_" PostSubject " ") 27 | (set 'topic-vote (int (last (first ($POST))))) ; we know it's an int because it was an $idx 28 | (set 'message-data (get-record "Posts" PostSubject)) 29 | (if message-data (begin 30 | (set 'message-data (first message-data)) 31 | ;(displayln "

Here is your message data:" message-data) 32 | (set 'Id (message-data 0)) ; this is the topic # for that post 33 | (set 'page-back (string "rockets-item.lsp?p=" Id "&f=true")) ; the page to go back to 34 | (set 'poll-data (message-data 8)) 35 | ;(displayln "

Here is your vote data:" topic-vote) 36 | ;(displayln "

Here is your poll data: " poll-data) 37 | ; First, check to see if you've already voted in this poll. 38 | (if (find (string Id "-") Rockets:UserPollsVoted) (begin 39 | (displayln "

Sorry, you've already voted in this poll!

") 40 | (displayln "

Click here to return to the poll thread.") 41 | ) 42 | (begin ; otherwise, go nuts! 43 | ; register that we've voted in the UserPollsVoted area 44 | (set 'UserPollsVoted (string Rockets:UserPollsVoted Id "-")) ; add this poll to polls visited 45 | (set 'UserId Rockets:UserId) ; make sure we update the user that's logged in! 46 | (update-record "Users" UserId UserPollsVoted) ; save to database 47 | (if (nil? poll-data) (begin ; if there's no data at all 48 | (set 'PostPoll (string topic-vote "-" 1 "_")) 49 | (displayln "

New poll data: " PostPoll " parsed: " (parse PostPoll "_")) 50 | (update-record "Posts" Id PostPoll) 51 | (page-redirect page-back) 52 | ) (begin 53 | ; there's already poll-data so we have to update it 54 | (displayln "

Existing poll data: " poll-data) 55 | (if (find (string topic-vote "-") poll-data) 56 | (begin 57 | (displayln "

Votes for this choice are here already!") 58 | (set 'position-of-vote (find (string topic-vote "-") poll-data)) 59 | (set 'end-position-of-vote (find "-" poll-data 0 position-of-vote)) 60 | (set 'end-position-of-tally (find "_" poll-data 0 end-position-of-vote)) 61 | (set 'old-vote (slice poll-data position-of-vote (- end-position-of-vote position-of-vote) 1)) 62 | (set 'new-vote (slice poll-data (+ end-position-of-vote 1) (- (- end-position-of-tally end-position-of-vote) 1))) 63 | (displayln "

Vote number: " old-vote) 64 | (displayln "

Vote value: " new-vote) 65 | (displayln "

New vote: " position-of-vote "," end-position-of-vote "," end-position-of-tally) 66 | ; bump up the new vote by 1 67 | (set 'new-vote (string (++ (int new-vote)))) 68 | (displayln "

New vote bumped by one: " new-vote) 69 | ; now recreate the string including the new vote 70 | (set 'new-poll-data (string (slice poll-data 0 end-position-of-vote) "-" new-vote (slice poll-data end-position-of-tally (- (length poll-data) end-position-of-tally)))) 71 | (displayln "

New poll data: " new-poll-data) 72 | (set 'PostPoll new-poll-data) 73 | (update-record "Posts" Id PostPoll) 74 | (page-redirect page-back) 75 | ) 76 | (begin 77 | (displayln "

No vote exists for this choice!") 78 | (set 'PostPoll (string poll-data topic-vote "-" 1 "_")) 79 | (update-record "Posts" Id PostPoll) 80 | (page-redirect page-back) 81 | ) 82 | ) 83 | )) 84 | )) 85 | )) 86 | 87 | ) 88 | ; not logged in 89 | (begin 90 | 91 | (displayln "

You must be signed in to vote!

") 92 | (displayln "

Return to the main page.

") 93 | )) 94 | (close-database) 95 | (display-footer RocketsConfig:Owner) 96 | (display-page) ; this is needed to actually display the page! 97 | 98 | -------------------------------------------------------------------------------- /rockets-post.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | (load "Rockets-config.lisp") ; load configuration information 6 | 7 | ; Rockets - Posting Page rockets-post.lsp 8 | ; 9 | ; This page takes a post in $POST and posts it to the Posts table, post-haste. Posts! 10 | ; Posts! 11 | (open-database RocketsConfig:Database) 12 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 13 | (display-partial "rockets-common-functions") ; add functions common to the blog but not the Rockets framework itself 14 | 15 | (if Rockets:UserId (begin ; must be a registered user to post anything 16 | 17 | (set 'max-posts (first (first (query "SELECT max(Id) from Posts")))) 18 | (displayln "

Max post id: " max-posts) 19 | 20 | (displayln "

$POST data: " ($POST)) 21 | 22 | ; if we have a post in $POST, post it to the Posts table. Tee hee! 23 | (set 'continue true) ; debugging 24 | (if continue (begin 25 | (if (and ($POST "post") ($POST "subjectline")) 26 | (begin 27 | (set 'post-type-trigger ($POST "optionalhidden")) ; this is a hidden value to make forum posts, not blog posts 28 | (set 'Id (+ max-posts 1)) 29 | (set 'PosterId Rockets:UserId) ; Any registered user may post, but only Admin may post blog posts 30 | (set 'PostType ($POST "posttype")) 31 | (set 'PostLastAuthor (author-name PosterId true)) 32 | (set 'PostSubject ($POST "subjectline")) 33 | (set 'PostContent ($POST "post")) 34 | (set 'PostDate (date (date-value) 0 "%Y-%m-%d %H:%M:%S.000")) 35 | (set 'PostLastDate PostDate) 36 | (set 'PostTags ($POST "tags")) 37 | (if (and (= PostType "Podcast") (or (nil? PostTags) (= PostTags ""))) (setq PostType "podcast")) ; if you don't set a tag for a podcast, set it to "podcast" 38 | (set 'PostPoll ($POST "polltopic")) ; for polls, adds text to post and info to database 39 | (set 'PostPollValues ($POST "pollvalues")) 40 | (displayln "Post Poll Values: " PostPoll ">>>") 41 | (if (not (= PostPoll "")) (begin 42 | (set 'poll-prepend-text (string "[h4]" PostPoll "[/h4]\n[poll]")) 43 | (set 'PostPollSubject PostSubject) ; we need a copy of this variable 44 | (replace " " PostPollSubject "_") ; this is to generate unique form names for each poll 45 | (set 'PostPollValues (parse PostPollValues "\n")) 46 | (dolist (p PostPollValues) 47 | (extend poll-prepend-text (string "\n" "[radio]" PostPollSubject " value=" $idx)) 48 | (if (= $idx 0) (extend poll-prepend-text " checked=yes")) 49 | (extend poll-prepend-text (string "[/radio] " p )) 50 | ) 51 | (set 'PostContent (string poll-prepend-text " [/poll]\n\n\n " PostContent)) 52 | )) 53 | (displayln "Post Type (before): " PostType) 54 | (if (nil? PostType) (begin ; regular users can make Forum Posts but nothing else, admins can make multiple PostTypes 55 | (if (= post-type-trigger "Forum") 56 | (set 'PostType "Forum post") 57 | (set 'PostType "Blog post")) 58 | )) 59 | (displayln "Post Type (after): " PostType) 60 | (create-record "Posts" Id PosterId PostDate PostSubject PostContent PostType PostTags PostLastAuthor PostLastDate) ; It's the C in CRUD! 61 | ; now update the user's postcount! postcount++!! 62 | (set 'UserId Rockets:UserId) 63 | (set 'UserPosts (++ Rockets:UserPosts)) 64 | (update-record "Users" UserId UserPosts) 65 | (if (= PostType "Podcast") (begin 66 | (displayln "

Adding podcast...

") 67 | ; add to the podcast XML feed in /podcast/ based on the podcast tag given 68 | ; if no podcast tag then just call it "podcast". 69 | ; this will all be in a partial file at some point - so we can remake the XML file even if we hit "edit" 70 | ; but that means we have to do a query and get all podcast posts each time 71 | (set 'quo (char 34)) ; quote character, we'll be using it a lot 72 | (set 'cr (append (char 13) (char 10))) ; carriage return + LF character 73 | (setq PostTags (force-parameters 1 PostTags)) ; one-word only podcasts (for now-- can fix later) 74 | (displayln "

Looking for podcasts with tag: " PostTags "

") 75 | (setq podcast-file (string "podcast/" PostTags ".xml")) ; PostTags for a podcast will be "podcast" if blank 76 | ; now we have to make the xml file. First, get all podcasts of the tag PostTag 77 | (setq podcast-feed (query (string "SELECT * FROM Posts WHERE PostType='Podcast' AND PostTags='" PostTags "' ORDER BY PostDate DESC;"))) 78 | (displayln "

Podcast query results:

" podcast-feed) 79 | (if podcast-feed (begin 80 | ; go through all results from the feed and save them to an XML file 81 | ; first, let's get the podcast config options from RocketsConfig (look for the tag in config, if no tag, use default config options) 82 | (setq podcast-ref (ref PostTags RocketsConfig:PodcastList)) 83 | (if (nil? podcast-ref) 84 | (setq podcast-settings '("podcast" "Podcast Title" "Podcast Copyright" "Podcast Subtitle" "Podcast Author" "Podcast Summary" "Podcast Owner" "Podcast Email" "Podcast Image" "Podcast Category" "Podcast Subcategory")) 85 | (setq podcast-settings (RocketsConfig:PodcastList (first podcast-ref))) 86 | ) 87 | (set 'silly-string " ") 88 | (set 'silly-string (append "")) 89 | (set 'silly-string (extend silly-string cr "")) 90 | (set 'silly-string (extend silly-string cr "")) 91 | (set 'silly-string (extend silly-string cr "" (podcast-settings 1) "")) 92 | (set 'silly-string (extend silly-string cr "" RocketsConfig:SiteURL "" "")) 93 | (set 'silly-string (extend silly-string cr "en-us")) 94 | (set 'silly-string (extend silly-string cr "" (podcast-settings 2) "")) 95 | (set 'silly-string (extend silly-string cr "" (podcast-settings 3) "")) 96 | (set 'silly-string (extend silly-string cr "" (podcast-settings 4) "")) 97 | (set 'silly-string (extend silly-string cr "" (podcast-settings 5) "")) 98 | (set 'silly-string (extend silly-string cr "" (podcast-settings 5) "")) 99 | (set 'silly-string (extend silly-string cr "" podcast-file "")) 100 | (set 'silly-string (extend silly-string cr "")) 101 | (set 'silly-string (extend silly-string cr "" (podcast-settings 6) "")) 102 | (set 'silly-string (extend silly-string cr "" (podcast-settings 7) "")) 103 | (set 'silly-string (extend silly-string cr "")) 104 | (set 'silly-string (extend silly-string cr "")) 105 | (set 'silly-string (extend silly-string cr "")) 106 | (set 'silly-string (extend silly-string cr "")) 107 | (set 'silly-string (extend silly-string cr "")) 108 | (dolist (x podcast-feed) 109 | ; add the XML for each episode of the podcast 110 | (set 'silly-string (extend silly-string cr "")) 111 | (set 'podcast-item-title (x 3)) 112 | (set 'podcast-item-subtitle (x 3)) 113 | (set 'podcast-item-summary (x 4)) 114 | (set 'podcast-item-date (date (integer (x 2)) 0 "%a, %d %b %Y %H:%M:%S %Z")) 115 | (set 'podcast-filename "temp-testing.mp3") ; TEMPORARY TEST!!!! CHANGE WHEN WE EDIT! 116 | (set 'podcast-item-duration "35:00") ; <- change obviously 117 | (set 'podcast-item-keywords "test, test, test") ; <- NEED TO ADD TO PODCAST CONFIG 118 | (set 'podcast-item-url (string RocketsConfig:SiteURL "/audio/" podcast-filename)) 119 | (set 'silly-string (extend silly-string cr "" podcast-item-summary "")) 120 | (set 'silly-string (extend silly-string cr "")) 121 | (set 'silly-string (extend silly-string cr "" podcast-item-url "")) 122 | (set 'silly-string (extend silly-string cr "" podcast-item-date "")) 123 | (set 'silly-string (extend silly-string cr "" podcast-item-duration "")) 124 | (set 'silly-string (extend silly-string cr "" podcast-item-keywords "")) 125 | (set 'silly-string (extend silly-string cr "")) 126 | ) 127 | (set 'silly-string (extend silly-string cr "Clean")) 128 | (set 'silly-string (extend silly-string cr "")) 129 | (set 'silly-string (extend silly-string cr "")) 130 | ; write the XML file to disk 131 | (write-file podcast-file silly-string) 132 | )) ; end if podcast-feed (if we got a result from query) 133 | )) ; end if PostType = 'Podcast' 134 | ) ; end section of posting post from POST 135 | ) 136 | )) ; end "if continue" check 137 | 138 | ; Generate a full RSS feed XML file for the blog 139 | (display-partial "rockets-generate-rss") 140 | 141 | )) ; end check to see if user is signed in 142 | 143 | (displayln "Click here to return to the main page.") ; for debugging 144 | (if (= PostType "Forum post") 145 | (page-redirect "rockets-forum.lsp") 146 | (page-redirect "rockets-main.lsp")) 147 | (display-page) 148 | -------------------------------------------------------------------------------- /rockets-profile.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-profile.lsp) - Rockets - User profile page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | 14 | (display-header (string RocketsConfig:Name " - Edit Profile")) 15 | (open-database RocketsConfig:Database) 16 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 17 | (set 'active-page "rockets-profile") 18 | (display-partial "rockets-navbar") 19 | 20 | (displayln "

User Profile

") 21 | 22 | (if Rockets:UserId (begin 23 | (displayln "

User Name: " Rockets:UserName) 24 | (displayln "

User Email: " Rockets:UserEmail) 25 | (displayln "

Total Posts: " Rockets:UserPosts) 26 | ; update birth date if user hit the Save button 27 | (if ($POST "date") (begin 28 | (set 'temp-date ($POST "date")) 29 | (set 'UserBirthDate (string (slice temp-date 6 4) "-" (slice temp-date 3 2) "-" (slice temp-date 0 2) " 00:00:00.000")) 30 | (set 'UserId Rockets:UserId) 31 | (if (update-record "Users" UserId UserBirthDate) 32 | (begin (display-success "Birth date saved!") (set 'Rockets:UserBirthDate temp-date)) 33 | (display-error "Error updating birth date. :(")) 34 | )) 35 | ; get birthdate from database 36 | (if Rockets:UserBirthDate 37 | (set 'show-birthdate Rockets:UserBirthDate) 38 | (set 'show-birthdate "01-01-1980")) ; default if not set 39 | (displayln "") 40 | (form-datepicker "Enter your birth date" "date" show-birthdate "dp1") 41 | (displayln "") 42 | (displayln "

") 43 | (displayln "

Avatar: ") 45 | (displayln "

Upload new avatar (all avatars scaled to 64x64 pixels):

") 46 | 47 | ) ; -- end section that shows if the user is signed in 48 | (displayln "

You must be signed in to view your user profile.

") 49 | ) 50 | 51 | 52 | 53 | (close-database) 54 | (display-footer RocketsConfig:Owner) 55 | (display-page) ; this is needed to actually display the page! -------------------------------------------------------------------------------- /rockets-register-confirm.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | (load "newlisp-rockets.lisp") 3 | (load "Rockets-config.lisp") ; load configuration information 4 | (display-header) 5 | (open-database RocketsConfig:Database) 6 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 7 | (display-partial "rockets-common-functions") ; loads functions common to the blog but not part of Rockets 8 | (set 'active-page "rockets-register-confirm") 9 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 10 | 11 | ; set Rockets cookie name (will be from a file later) 12 | (set 'rocket-cookie-name "rockets-4dckq3-e4jcx-2wgxc") 13 | 14 | (module "crypto.lsp") 15 | 16 | (set 'UserPassword ($GET "p")) 17 | (set 'UserConfirmPassword ($GET "c")) 18 | (set 'UserName ($GET "u")) 19 | (set 'UserEmail ($GET "e")) 20 | 21 | (load "rocket-list.lisp") ; load up RocketReg:rocket-list and RocketReg:not-rocket-list 22 | (set 'found-rockets 0) 23 | (dolist (z RocketReg:rocket-list) 24 | (display "
**" (string "r" z) " GET: " ($GET (string z))) 25 | (if ($GET (string z)) (++ found-rockets)) 26 | (set (sym (string "r" z)) ($GET (string z))) 27 | ;(print (sym (string "k" z))) 28 | ) 29 | (set 'found-not-rockets 0) 30 | (dolist (q RocketReg:not-rocket-list) 31 | (if ($GET (string q)) (++ found-not-rockets)) 32 | ) 33 | 34 | (displayln "

>>TOTAL FOUND ROCKETS: " found-rockets) 35 | (displayln "

>>TOTAL FOUND NOTROCKETS: " found-not-rockets) 36 | 37 | (if (< found-rockets 3) (page-redirect "rockets-register" "e=few")) 38 | (if (> found-not-rockets 0) (page-redirect "rockets-register" "e=many")) 39 | 40 | ; now check these things to see if they are acceptable 41 | 42 | ; first check to see if the user name or email exists in the database already 43 | (if (query (string "SELECT * FROM Users WHERE UserName='" (trim UserName) "'")) (page-redirect "rockets-register" "e=samename")) 44 | (if (query (string "SELECT * FROM Users WHERE UserEmail='" (trim UserEmail) "'")) (page-redirect "rockets-register" "e=samename")) 45 | (if (= (trim UserName) "") (page-redirect "rockets-register" "e=noname")) 46 | (if (= (trim UserPassword) "") (page-redirect "rockets-register" "e=nopw")) 47 | (if (!= UserPassword UserConfirmPassword) (page-redirect "rockets-register" "e=pwmatch")) 48 | (if (= (trim UserEmail) "") (page-redirect "rockets-register" "e=noemail")) 49 | 50 | ; everything checked out, let's register this person! 51 | (displayln (query "pragma table_info('Users')")) 52 | (set 'UserId (+ (int (first (first (query "select MAX(UserId) from Users")))) 1)) 53 | (displayln "
UserId: " UserId) 54 | (displayln "
UserEmail: " UserEmail) 55 | (displayln "
UserPassword: " UserPassword) 56 | (set 'UserSalt (uuid)) 57 | (set 'UserPasswordHash (crypto:sha1 (string UserSalt UserPassword))) 58 | (displayln "
UserSalt: " UserSalt) 59 | (displayln "
UserPasswordHash: " UserPasswordHash) 60 | (set 'CookieSalt (uuid)) 61 | (displayln "
UserSalt: " CookieSalt) 62 | (set 'UserPosts 0) 63 | (displayln "
UserPosts: " UserPosts) 64 | (displayln "
UserName: " UserName) 65 | 66 | (create-record "Users" UserId UserEmail UserPasswordHash UserSalt UserPosts CookieSalt UserName) 67 | (displayln (query (string "select * from Users"))) 68 | ; set the cookie 69 | (set 'new-cookie (string UserId "|" CookieSalt)) 70 | (set-cookie rocket-cookie-name new-cookie (+ (date-value) (* 60 60 24 365))) ; set cookie for one year from now 71 | 72 | ; one last thing, send a nice email welcoming the new user! 73 | (set 'welcome-email "Thank you for registering. If you have any questions, please don't hesitate to email me or post a comment on the blog.\n\nSincerely,\n\nRocket Man") 74 | (send-mail UserEmail "newlisponrockets@newlisponrockets.com" "Rocket Man" "Welcome to the newLISP on Rockets blog!" welcome-email) 75 | ; and send a mail to me so that I know that a new user registered! 76 | (set 'new-user-registered-mail (string "A new user by the name of: " UserName " just registered with the email address " UserEmail ".")) 77 | (send-mail "newlisponrockets@newlisponrockets.com" "newlisponrockets@newlisponrockets.com" "Rocket Man" "A new user has registered on the newLISP on Rockets blog" new-user-registered-mail) 78 | 79 | 80 | (page-redirect "rockets-main" "e=newuser") 81 | 82 | (display-footer RocketsConfig:Owner) 83 | (display-page) 84 | -------------------------------------------------------------------------------- /rockets-register.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-verify.lsp) - Rockets - Registration page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header (string RocketsConfig:Name " - Register")) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (set 'active-page "rockets-register") 17 | (display-partial "rockets-navbar") 18 | 19 | (displayln "

Register for the Rockets Blog!

") 20 | (displayln "

Tired of having to squint at distorted letters just to register for a new website? So are we. So let's try something more fun.

") 21 | 22 | (load "rocket-list.lisp") 23 | (set 'total-critter-list-num (append RocketReg:rocket-list RocketReg:not-rocket-list)) 24 | (dolist (q total-critter-list-num) 25 | (set 'temp-critter (string q)) 26 | (push temp-critter total-critter-list -1)) 27 | 28 | ; note: "cats" are rockets. "not-cats" are other vehicles. 29 | (seed (time-of-day)) 30 | (do-until (= (length (unique new-cat-list)) 3) (set 'new-cat-list (rand 9 3))) ; keep doing it until you get 3 distinct cats 31 | (set 'new-not-cat-list-temp (rand (- 91 9) 9)) 32 | (dolist (y new-not-cat-list-temp) (push (+ y 9) new-not-cat-list -1)) 33 | 34 | (set 'total-animal-list (append new-cat-list new-not-cat-list)) 35 | (set 'total-animal-list (randomize total-animal-list)) 36 | 37 | (displayln "

Can you find the rockets?

") 38 | (displayln "

Please click the checkboxes below all three rockets, to prove you are a human.

") 39 | (displayln "

Then, enter a user name, password, and email address below and click 'Register'.

") 40 | (displayln "

You will be registered and signed in automatically.

") 41 | 42 | (displayln "
") 43 | 44 | (displayln "") 45 | (set 'cat-counter 0) 46 | (dolist (z total-animal-list) 47 | (if (= cat-counter 0) (displayln "")) 48 | (++ cat-counter) 49 | (displayln "") 53 | (if (> cat-counter 5) (begin (displayln "") (set 'cat-counter 0))) 54 | ) 55 | (displayln "
") 50 | (displayln "") 51 | (displayln "
") 52 | (displayln "
") 56 | 57 | (if (= error-messages "few") (begin (display "
") 58 | (display-error "Warning! Danger Will Robinson! Not enough rockets! You need to select three of them."))) 59 | (if (= error-messages "many") (begin (display "
") 60 | (display-error "Warning! Danger Will Robinson! You selected something that wasn't a rocket!"))) 61 | 62 | (displayln "") 63 | ; Email address (user name) 64 | (displayln "


") 65 | (displayln "") 69 | ; Password 70 | (displayln "") 74 | (displayln "") 78 | ; Display name 79 | (displayln "") 85 | 86 | 87 | (displayln "") 88 | (displayln "
Email (This is your User Name):") 66 | (if (= error-messages "noemail") 67 | (display-error "You must enter an email address.")) 68 | (displayln "
Password:") 71 | (if (= error-messages "nopw") 72 | (display-error "You must enter a password.")) 73 | (displayln "
Confirm password:") 75 | (if (= error-messages "pwmatch") 76 | (display-error "Passwords did not match!")) 77 | (displayln "
Display name:") 80 | (if (= error-messages "samename") 81 | (display-error "Somebody with the same name or email address is already registered here.")) 82 | (if (= error-messages "noname") 83 | (display-error "You must enter a display name.")) 84 | (displayln "



") 89 | 90 | 91 | (close-database) 92 | (display-footer RocketsConfig:Owner) 93 | (display-page) ; this is needed to actually display the page! -------------------------------------------------------------------------------- /rockets-signout.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-signout.lsp) - Rockets - User sign out page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header (string RocketsConfig:Name " - Sign Out")) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (set 'active-page "rockets-main") 17 | (display-partial "rockets-navbar") ; shows the navigation bar with Rockets blog menus 18 | 19 | (start-div "hero-unit") 20 | (displayln "

" RocketsConfig:Name "

") 21 | (displayln "

Currently running newLISP on Rockets version: " $ROCKETS_VERSION "

") 22 | (end-div) 23 | 24 | (if Rockets:UserId 25 | (begin 26 | (delete-cookie rocket-cookie-name) 27 | (page-redirect "rockets-signout") 28 | ) 29 | (begin 30 | (displayln "

You are now signed out of " RocketsConfig:Name ".

") 31 | (displayln "

Click here to return to the main page.") 32 | ) 33 | ) 34 | 35 | (close-database) 36 | (display-footer RocketsConfig:Owner) 37 | (display-page) ; this is needed to actually display the page! 38 | -------------------------------------------------------------------------------- /rockets-verify.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-verify.lsp) - Rockets - User verification page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; This page just verifies that a user entered the correct credentials 11 | ; Written 2012 by Rocket Man 12 | 13 | (load "Rockets-config.lisp") ; load configuration information 14 | (display-header) 15 | 16 | (module "crypto.lsp") 17 | 18 | (open-database RocketsConfig:Database) 19 | (display-partial "rockets-common-functions") 20 | 21 | ; set Rockets cookie name (from common functions) 22 | (set 'rocket-cookie-name Blog:rocket-cookie-name) 23 | 24 | (set 'UserEmail ($POST "email")) 25 | (set 'UserPassword ($POST "password")) 26 | (set 'page-to-redirect ($POST "activepage")) 27 | ; we might not get a redirect page value from the form, so set a default one if it doesn't exit 28 | (if (or (nil? page-to-redirect) (= page-to-redirect "nil")) (set 'page-to-redirect "rockets-main")) 29 | 30 | ; a lot of this stuff is temporary until we figure out how to make this part of the framework 31 | (set 'sql-result (get-record "Users" UserEmail)) 32 | (if sql-result (begin 33 | (set 'sql-result (first sql-result)) 34 | (set 'sql-user-id (sql-result 0)) 35 | (set 'sql-password-hash (sql-result 2)) 36 | (set 'sql-password-salt (sql-result 3)) 37 | (set 'sql-cookie-salt (sql-result 8)) 38 | (set 'hash-combination (crypto:sha1 (string sql-password-salt UserPassword))) 39 | 40 | (if (= sql-password-hash hash-combination) (begin 41 | (displayln "
Password correct!") 42 | (set 'temp-cookie-hash (string "user=" (string sql-user-id "|" sql-cookie-salt))) 43 | (displayln "
Cookie set: " temp-cookie-hash) 44 | ; set a cookie 45 | (set-cookie rocket-cookie-name temp-cookie-hash (+ (date-value) (* 60 60 24 365))) ; set cookie expiry to one year from now 46 | (displayln "
You have succesfully logged in! Click here to continue.") 47 | (page-redirect page-to-redirect) 48 | ) 49 | (begin 50 | (page-redirect page-to-redirect "e=signin-p") ; tell the application that the password was not recognized. 51 | ) 52 | ) 53 | ) 54 | (begin 55 | (page-redirect page-to-redirect "e=signin-u") ; tell the application that the username was not recognized. 56 | )) 57 | 58 | (close-database) 59 | (display-footer RocketConfig:Owner) 60 | (display-page) ; this is needed to actually display the page! 61 | -------------------------------------------------------------------------------- /rockets-why.lsp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env newlisp 2 | 3 | (load "newlisp-rockets.lisp") ; this is where the magic happens! 4 | 5 | ; (rockets-verify.lsp) - Rockets - User verification page 6 | ; 7 | ; This is the first version of the self-hosted blog for newLISP on Rockets. 8 | ; The blog is designed to showcase how you would use Rockets for a real application. 9 | ; 10 | ; Written 2012 by Rocket Man 11 | 12 | (load "Rockets-config.lisp") ; load configuration information 13 | (display-header (string RocketsConfig:Name " - Why Rockets?")) 14 | (open-database RocketsConfig:Database) 15 | (display-partial "rockets-checksignin") ; checks to see if user is signed in 16 | (set 'active-page "rockets-why") 17 | (display-partial "rockets-navbar") 18 | 19 | (displayln "

Why newLISP on Rockets?

") 20 | 21 | (displayln "

Why indeed? Why create yet another framework using yet another language? What do you hope to accomplish?") 22 | (displayln "

Let me tell you a story.

") 23 | (display-image "eniac4.gif") 24 | (displayln "

In the beginning

") 25 | (displayln "

The first computers weren't really programmable as such. You would plug in patch cables to") 26 | (displayln "physically rewire the system. This was quickly replaced with binary code, where instructions and data were") 27 | (displayln "entered alternately in chunks. Usually it was instruction, then data, or instruction then data then data. The") 28 | (displayln "code and the data were the same: it was just the order they came in that mattered. Remember this for later.

") 29 | (displayln "

Languages

") 30 | (displayln "

Binary code was converted to hexadecimal for simplicity and easier recognition. Then someone had the bright idea to") 31 | (displayln "have the computer translate three or four digit mnemonics for the instructions, so instead of issuing instruction 8B you could") 32 | (displayln "say MOV instead. Now, the instructions stopped looking like the data. The computer still saw them the same, but the") 33 | (displayln "programmer no longer did.

") 34 | (displayln "

High level languages continued this trend, abstracting huge chunks of assembly language code in order to simplify life") 35 | (displayln "for the programmer. Lots of high-level languages were developed in the 1950s, and they left a long shadow in the computer world:") 36 | (displayln "

") 40 | (displayln "

Why LISP?

") 41 | (displayln "

The one thing that LISP does that no other languages do is that data is written exactly the same way as code. This is the sort of") 42 | (displayln "brilliant idea that takes a while to really sink in. The fundamental structure of LISP is lists. Your data is in lists. Your code is in lists. ") 43 | (displayln "Everything is a function, and defining new functions is trivial, so you start extending the language without even realizing it.") 44 | (displayln "A function is just a list with the first element in the list being special and the rest being data. Older LISPs had functions to extract") 45 | (displayln "the first element and the rest of the elements, called CAR and CDR because it was based on IBM assembly language instructions. In newLISP, these") 46 | (displayln "functions are more sensibly called (first) and (rest).") 47 | (displayln "

Like many people, I encountered LISP in university and never quite 'grokked' why it was so special. Many years later I came across") 48 | (displayln "Paul Graham's essay called Beating the Averages and got very excited about the idea of outperforming") 49 | (displayln "much larger programming teams by using a 'secret' language that everyone else ignored. It's a classic David-versus-Goliath scenario, and very appealing.") 50 | (displayln "But would it actually work in real life? I decided to try it. To my surprise, it worked exactly as advertised.") 51 | (displayln "

But surely the world has moved on, hasn't it? The stuff Paul Graham's two-person team was doing was back in the late 1990s. We have much better tools now, right?

") 52 | (displayln "

Wrong. We have bigger tools, with more features, that take longer to learn. Every few years there is a new 'sexy' language") 53 | (displayln "or framework that promises to simplify things, and many them are quite good, like Ruby on Rails. But none of them can ever have code that is the same as data.") 54 | (displayln "They can't. If they did, they would be LISP.") 55 | (displayln "

So why newLISP?

") 56 | (displayln "

There are a lot of LISP dialects out there. The standard one is Common Lisp, which has grown and congealed over the years to become something") 57 | (displayln "much more complicated than it needs to be. There are new languages like Clojure, but as neat as it is it comes with the complexity of Java bolted underneath it.

") 58 | (displayln "

There are other dialects like PicoLisp and newLISP that aimed at being simple, small, and fast. I chose newLISP because someone had written a really cool") 59 | (displayln "web development framework called Dragonfly that made it ridiculously easy to make new web applications.") 60 | (displayln "

Okay, so why Rockets?

") 61 | (displayln "

As great as Dragonfly is, something kept pulling me towards writing a replacement. It's a testament to LISP's power that doing so was even possible. ") 62 | (displayln "Working with LISP makes you think you can do all sorts of crazy things. I wanted a framework that simplified database work and jQuery access, something that ") 63 | (displayln "Dragonfly didn't do, and wasn't likely to do as development seems to have stopped. I just decided to start doing it, just for fun, just because I wanted to.") 64 | (displayln "

And here we are.") 65 | (displayln "

So why should I use Rockets?

") 66 | (displayln "

You should use Rockets if you are looking for rapid application development or prototyping. You should use Rockets if you want really fast performance. You should") 67 | (displayln "use Rockets if you want these things and want your life to be simple. Modern web developers have to keep a lot of things in their heads and have to constantly learn new") 68 | (displayln "technologies. They have to worry about having a nice GUI with flashy Javascript things. They have to worry about things like SQL injection and cross-site scripting attacks and salting passwords and all sorts of other things that keep popping up.

") 69 | (displayln "

Rockets is designed to take care of a lot of things for you, so you can think about what your awesome new application will actually do.") 70 | 71 | 72 | (close-database) 73 | (display-footer RocketsConfig:Owner) 74 | (display-page) ; this is needed to actually display the page! -------------------------------------------------------------------------------- /setup-rockets.lisp: -------------------------------------------------------------------------------- 1 | ; setup-rockets.lisp - Sets up database and tables for a new installation of newLISP on Rockets 2 | ; 3 | ; Includes Users, Posts, and Comments for a bulletin-board and blog type setup 4 | 5 | (define (displayln str) 6 | (println str)) 7 | 8 | (define (open-database sql-db-to-open) 9 | (if (sql3:open (string sql-db-to-open ".db")) 10 | (displayln "") 11 | (displayln "There was a problem opening the database " sql-db-to-open ": " (sql3:error)))) 12 | 13 | (define (close-database) 14 | (if (sql3:close) 15 | (displayln "") 16 | (displayln "There was a problem closing the database: " (sql3:error)))) 17 | 18 | (define (query sql-text) 19 | (set 'sqlarray (sql3:sql sql-text)) ; results of query 20 | (if sqlarray 21 | (setq query-return sqlarray) 22 | (if (sql3:error) 23 | (displayln (sql3:error) " query problem ") 24 | (setq query-return nil)))) 25 | 26 | (define (safe-for-sql str-sql-query) 27 | (if (string? str-sql-query) (begin 28 | (replace "&" str-sql-query "&") 29 | (replace "'" str-sql-query "'") 30 | (replace "\"" str-sql-query """) 31 | )) 32 | (set 'result str-sql-query)) 33 | 34 | (define-macro (create-record) 35 | ; first save the values 36 | (set 'temp-record-values nil) 37 | (set 'temp-table-name (first (args))) 38 | ;(displayln "
Arguments: " (args)) 39 | (dolist (s (rest (args))) (push (eval s) temp-record-values -1)) 40 | ; now save the arguments as symbols under the context "DB" 41 | (dolist (s (rest (args))) 42 | (set 'temp-index-num (string $idx)) ; we need to number the symbols to keep them in the correct order 43 | (if (= (length temp-index-num) 1) (set 'temp-index-num (string "0" temp-index-num))) ; leading 0 keeps the max at 100. 44 | (sym (string temp-index-num s) 'DB)) 45 | ; now create the sql query 46 | (set 'temp-sql-query (string "INSERT INTO " temp-table-name " (")) 47 | ;(displayln "

TABLE NAME: " temp-table-name) 48 | ;(displayln "

SYMBOLS: " (symbols DB)) 49 | ;(displayln "
VALUES: " temp-record-values) 50 | (dolist (d (symbols DB)) (extend temp-sql-query (rest (rest (rest (rest (rest (string d)))))) ", ")) 51 | (set 'temp-sql-query (chop (chop temp-sql-query))) 52 | (extend temp-sql-query ") VALUES (") 53 | (dolist (q temp-record-values) 54 | (if (string? q) (extend temp-sql-query "'")) ; only quote if value is non-numeric 55 | (extend temp-sql-query (string (safe-for-sql q))) 56 | (if (string? q) (extend temp-sql-query "'")) ; close quote if value is non-numeric 57 | (extend temp-sql-query ", ")) ; all values are sanitized to avoid SQL injection 58 | (set 'temp-sql-query (chop (chop temp-sql-query))) 59 | (extend temp-sql-query ");") 60 | ;(displayln "

***** SQL QUERY: " temp-sql-query) 61 | (displayln (query temp-sql-query)) ; actually run the query against the database 62 | (delete 'DB) ; we're done, so delete all symbols in the DB context. 63 | ) 64 | 65 | 66 | 67 | 68 | (module "crypto.lsp") 69 | (module "sqlite3.lsp") ; loads the SQLite3 database module 70 | 71 | (set 'table1 "CREATE TABLE Posts (Id INTEGER PRIMARY KEY, PosterId TEXT, PostDate DATE, PostSubject TEXT, PostContent TEXT, PostComments INTEGER, PostType TEXT, PostViews INTEGER, PostPoll TEXT, PostTags TEXT, PostLastAuthor TEXT, PostLastDate DATE)") 72 | (set 'table2 "CREATE TABLE Users (UserId INTEGER PRIMARY KEY, UserEmail TEXT, UserPasswordHash TEXT, UserSalt TEXT, UserPosts INTEGER, UserAchievements TEXT, UserReadPosts TEXT, UserName TEXT, CookieSalt TEXT, UserAvatar TEXT, UserBirthdate DATE, UserJoinedDate DATE, UserPollsVoted TEXT)") 73 | (set 'table3 "CREATE TABLE Comments (Id INTEGER PRIMARY KEY, PostId INTEGER, CommenterId INTEGER, CommentDate DATE, CommentSubject TEXT, CommentContent TEXT)") 74 | 75 | (println "This is a VERY RUDIMENTARY setup for the newLISP on Rockets database!") 76 | (println) 77 | (println "Now creating database...") 78 | ;(open-database database-name) 79 | (println "Please enter a name for your blog (eg: The newLISP on Rockets Blog)") 80 | (set 'RocketsConfig:Name (read-line)) 81 | (println "Now enter a short version of this name to appear on the header (eg: newLISP on Rockets)") 82 | (set 'RocketsConfig:ShortName (read-line)) 83 | (println "Now enter the URL (minus the http://) of the blog (eg: newlisponrockets.com)") 84 | (set 'RocketsConfig:SiteURL (read-line)) 85 | (println "Now enter the owner of the blog (eg: Rocket Man)") 86 | (set 'RocketsConfig:Owner (read-line)) 87 | (println "Now setting up Posts, Users, and Comments tables...") 88 | (print "Enter a database name (.db extension added automatically): ") 89 | (set 'database-name (upper-case (read-line))) 90 | (set 'RocketsConfig:Database database-name) 91 | (print "Enter a user name for the ADMIN user (case sensitive): ") 92 | (set 'UserName (read-line)) 93 | (print "Enter an email for the ADMIN user (case sensitive): ") 94 | (set 'UserEmail (read-line)) 95 | (set 'RocketsConfig:AdminEmail UserEmail) ; add this to config file 96 | (print "Now enter a password for the ADMIN user (case sensitive): ") 97 | (set 'password (read-line)) 98 | (set 'UserSalt (uuid)) 99 | (set 'CookieSalt (uuid)) 100 | (println "Salt: " UserSalt) 101 | (println "Cookie Salt: " CookieSalt) 102 | (set 'UserPasswordHash (crypto:sha1 (string UserSalt password))) 103 | (println "Password hash: " UserPasswordHash) 104 | (set 'UserId 0) ; Admin user is always UserId 0 105 | (set 'UserPosts 0) ; start from the bottom! 106 | 107 | ; set the default front page configuration 108 | (set 'RocketsConfig:FrontPageType 1) 109 | 110 | ; set the default individual page configuration 111 | (set 'RocketsConfig:IndividualPageType 0) 112 | 113 | ; save the configuration file 114 | (save "Rockets-config.lisp" 'RocketsConfig) 115 | 116 | ; create the database 117 | (open-database database-name) 118 | 119 | (query table1) 120 | (query table2) 121 | (query table3) 122 | 123 | (create-record "Users" UserId UserEmail UserPasswordHash UserSalt UserPosts UserName CookieSalt) 124 | 125 | ; now make a default post 126 | ;Id INTEGER PRIMARY KEY, PosterId TEXT, PostDate DATE, PostSubject TEXT, PostContent TEXT, PostComments INTEGER, PostType TEXT) 127 | (set 'Id 0) ; first post # is always 0 128 | (set 'PosterId 0) ; posted by admin user 129 | (set 'PostDate (date (date-value) 0 "%Y-%m-%d %H:%M:%S.000")) 130 | (set 'PostSubject "This is a test post") 131 | (set 'PostContent "This is a test post to make sure the blog code works from scratch. After you have added a new post yourself, you can delete this one.") 132 | (set 'PostType "Blog post") 133 | (set 'PostLastDate PostDate) 134 | (set 'PostLastAuthor "Rocket Man") 135 | (create-record "Posts" Id PosterId PostDate PostSubject PostContent PostType PostLastDate PostLastAuthor) 136 | 137 | ; check to see if it worked! 138 | (set 'user-table (query "select * from Posts")) 139 | (println "User data: " user-table) 140 | (close-database) 141 | (exit) 142 | -------------------------------------------------------------------------------- /upgrade.lisp: -------------------------------------------------------------------------------- 1 | ; upgrade.lisp - upgrades the database from Rockets 0.x to 2.0 2 | 3 | (define (displayln str) 4 | (println str)) 5 | 6 | (define (open-database sql-db-to-open) 7 | (if (sql3:open (string sql-db-to-open ".db")) 8 | (displayln "") 9 | (displayln "There was a problem opening the database " sql-db-to-open ": " (sql3:error)))) 10 | 11 | (define (close-database) 12 | (if (sql3:close) 13 | (displayln "") 14 | (displayln "There was a problem closing the database: " (sql3:error)))) 15 | 16 | (define (query sql-text) 17 | (set 'sqlarray (sql3:sql sql-text)) ; results of query 18 | (if sqlarray 19 | (setq query-return sqlarray) 20 | (if (sql3:error) 21 | (displayln (sql3:error) " query problem ") 22 | (setq query-return nil)))) 23 | (module "crypto.lsp") 24 | (module "sqlite3.lsp") ; loads the SQLite3 database module 25 | 26 | 27 | (load "Rockets-config.lisp") ; load configuration information 28 | (open-database RocketsConfig:Database) 29 | (query "ALTER TABLE Posts ADD PostTags TEXT;") 30 | (query "ALTER TABLE Posts ADD PostLastAuthor TEXT;") 31 | (query "ALTER TABLE Posts ADD PostLastDate DATE;") 32 | 33 | ; go through all posts and find the last author and last author date 34 | (set 'all-posts (query "SELECT * FROM Posts;")) 35 | (dolist (p all-posts) 36 | (set 'replies (query (string "SELECT * FROM Comments WHERE PostId=" (p 0)))) 37 | (if replies (begin 38 | (setq final-reply (last replies)) 39 | (print "FINAL AUTHOR: " (final-reply 2)) 40 | (setq final-author (query (string "SELECT UserName from Users WHERE UserId=" (final-reply 2)))) 41 | (print "FINAL AUTHOR: " final-author) 42 | (setq last-author (first (first final-author))) 43 | (setq last-date (final-reply 3)) 44 | (println "LAST AUTHOR **COMMENT**:::>>>>>>>>>" last-author) 45 | (println "LAST DATE **COMMENT**:::>>>>>>>>>" last-date) 46 | ) (begin 47 | (setq last-author (first (first (query (string "SELECT UserName from Users WHERE UserId=" (p 1)))))) 48 | (setq last-date (p 2)) 49 | (println "LAST AUTHOR:::>>>>>>>>>" last-author) 50 | (println "LAST DATE:::>>>>>>>>>" last-date) 51 | )) 52 | (query (string "UPDATE Posts SET PostLastAuthor = '" last-author "', PostLastDate = '" last-date "' WHERE Id=" (p 0))) 53 | ) 54 | 55 | 56 | (close-database) 57 | (exit) 58 | 59 | --------------------------------------------------------------------------------