├── .gitignore ├── App.svelte ├── DelUserForm.svelte ├── EditUserForm.svelte ├── Grid.svelte ├── LICENSE ├── LoginForm.svelte ├── Makefile ├── README.md ├── RSSView.svelte ├── SignupForm.svelte ├── about.html ├── archive ├── Drag.svelte ├── drag.html ├── drag_svelte.html ├── drag_svelte.js ├── drag_vanilla.js └── rssparts.html ├── cheveron-down.svg ├── freerss.go ├── index.html ├── index.js ├── menu.svg ├── postcss.config.js ├── refresh.svg ├── rollup.config.js ├── screenshots ├── freerss_portal.png └── freerss_withpreview.png ├── spec.txt ├── static ├── coffee.ico └── radio.ico ├── tailwind.config.js └── twsrc.css /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.o 3 | *.db 4 | *.map 5 | node_modules 6 | package.json 7 | package-lock.json 8 | static/style.css 9 | static/bundle.css 10 | static/bundle.js 11 | freerss 12 | 13 | -------------------------------------------------------------------------------- /App.svelte: -------------------------------------------------------------------------------- 1 |
You don't have any widgets yet.
303 | Add a new widget or
304 | Add sample widgets
305 |
Loading...
309 | {/if} 310 |FreeRSS v1
21 |RSS Viewer and Web Portal
22 |Copyright (c) 2020 by Rob de la Cruz
23 | 24 |Support FreeRSS Development and Hosting
25 | 26 |Some text %s.
", str) 336 | // fmt.Fprintf(w, "Some other text %s.
", str) 337 | // with the shorter version: 338 | // P := makeFprintf(w) 339 | // P("Some text %s.
", str) 340 | // P("Some other text %s.
", str) 341 | func makeFprintf(w io.Writer) func(format string, a ...interface{}) (n int, err error) { 342 | return func(format string, a ...interface{}) (n int, err error) { 343 | return fmt.Fprintf(w, format, a...) 344 | } 345 | } 346 | func listContains(ss []string, v string) bool { 347 | for _, s := range ss { 348 | if v == s { 349 | return true 350 | } 351 | } 352 | return false 353 | } 354 | func fileExists(file string) bool { 355 | _, err := os.Stat(file) 356 | if err != nil && os.IsNotExist(err) { 357 | return false 358 | } 359 | return true 360 | } 361 | func makePrintFunc(w io.Writer) func(format string, a ...interface{}) (n int, err error) { 362 | // Return closure enclosing io.Writer. 363 | return func(format string, a ...interface{}) (n int, err error) { 364 | return fmt.Fprintf(w, format, a...) 365 | } 366 | } 367 | func atoi(s string) int { 368 | if s == "" { 369 | return 0 370 | } 371 | n, err := strconv.Atoi(s) 372 | if err != nil { 373 | return 0 374 | } 375 | return n 376 | } 377 | func idtoi(sid string) int64 { 378 | return int64(atoi(sid)) 379 | } 380 | func itoa(n int64) string { 381 | return strconv.FormatInt(n, 10) 382 | } 383 | func atof(s string) float64 { 384 | if s == "" { 385 | return 0.0 386 | } 387 | f, err := strconv.ParseFloat(s, 64) 388 | if err != nil { 389 | return 0.0 390 | } 391 | return f 392 | } 393 | 394 | func unescapeUrl(qurl string) string { 395 | returl := "/" 396 | if qurl != "" { 397 | returl, _ = url.QueryUnescape(qurl) 398 | } 399 | return returl 400 | } 401 | func escape(s string) string { 402 | return html.EscapeString(s) 403 | } 404 | 405 | func parseArgs(args []string) (map[string]string, []string) { 406 | switches := map[string]string{} 407 | parms := []string{} 408 | 409 | standaloneSwitches := []string{} 410 | definitionSwitches := []string{"i"} 411 | fNoMoreSwitches := false 412 | curKey := "" 413 | 414 | for _, arg := range args { 415 | if fNoMoreSwitches { 416 | // any arg after "--" is a standalone parameter 417 | parms = append(parms, arg) 418 | } else if arg == "--" { 419 | // "--" means no more switches to come 420 | fNoMoreSwitches = true 421 | } else if strings.HasPrefix(arg, "--") { 422 | switches[arg[2:]] = "y" 423 | curKey = "" 424 | } else if strings.HasPrefix(arg, "-") { 425 | if listContains(definitionSwitches, arg[1:]) { 426 | // -a "val" 427 | curKey = arg[1:] 428 | continue 429 | } 430 | for _, ch := range arg[1:] { 431 | // -a, -b, -ab 432 | sch := string(ch) 433 | if listContains(standaloneSwitches, sch) { 434 | switches[sch] = "y" 435 | } 436 | } 437 | } else if curKey != "" { 438 | switches[curKey] = arg 439 | curKey = "" 440 | } else { 441 | // standalone parameter 442 | parms = append(parms, arg) 443 | } 444 | } 445 | 446 | return switches, parms 447 | } 448 | 449 | func handleErr(w http.ResponseWriter, err error, sfunc string) { 450 | log.Printf("%s: server error (%s)\n", sfunc, err) 451 | http.Error(w, fmt.Sprintf("%s", err), 500) 452 | } 453 | func handleDbErr(w http.ResponseWriter, err error, sfunc string) bool { 454 | if err == sql.ErrNoRows { 455 | http.Error(w, "Not found.", 404) 456 | return true 457 | } 458 | if err != nil { 459 | log.Printf("%s: database error (%s)\n", sfunc, err) 460 | http.Error(w, "Server database error.", 500) 461 | return true 462 | } 463 | return false 464 | } 465 | func handleTxErr(tx *sql.Tx, err error) bool { 466 | if err != nil { 467 | tx.Rollback() 468 | return true 469 | } 470 | return false 471 | } 472 | 473 | func genHash(sinput string) string { 474 | bsHash, err := bcrypt.GenerateFromPassword([]byte(sinput), bcrypt.DefaultCost) 475 | if err != nil { 476 | return "" 477 | } 478 | return string(bsHash) 479 | } 480 | func validateHash(shash, sinput string) bool { 481 | if shash == "" && sinput == "" { 482 | return true 483 | } 484 | err := bcrypt.CompareHashAndPassword([]byte(shash), []byte(sinput)) 485 | if err != nil { 486 | return false 487 | } 488 | return true 489 | } 490 | 491 | func findUser(db *sql.DB, username string) *User { 492 | s := "SELECT user_id, username, password FROM user WHERE username = ?" 493 | row := db.QueryRow(s, username) 494 | var u User 495 | err := row.Scan(&u.Userid, &u.Username, &u.HashedPwd) 496 | if err == sql.ErrNoRows { 497 | return nil 498 | } 499 | if err != nil { 500 | return nil 501 | } 502 | return &u 503 | } 504 | func isUsernameExists(db *sql.DB, username string) bool { 505 | if findUser(db, username) == nil { 506 | return false 507 | } 508 | return true 509 | } 510 | 511 | func feedHandler(db *sql.DB, gfparser *gofeed.Parser) http.HandlerFunc { 512 | return func(w http.ResponseWriter, r *http.Request) { 513 | qurl := unescapeUrl(r.FormValue("url")) 514 | if qurl == "" { 515 | http.Error(w, "?url=This is markup containing an inline script. 1029 | click me 1030 |
1031 | `, 1032 | Author: &feeds.Author{}, 1033 | Created: now, 1034 | } 1035 | f.Items = []*feeds.Item{ 1036 | &item, 1037 | } 1038 | rss, err := f.ToRss() 1039 | if err != nil { 1040 | handleErr(w, err, "testfeedHandler") 1041 | return 1042 | } 1043 | P("%s\n", rss) 1044 | } 1045 | } 1046 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |