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

wiki.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package repo
  6. import (
  7. "fmt"
  8. "io/ioutil"
  9. "net/url"
  10. "path/filepath"
  11. "strings"
  12. "code.gitea.io/gitea/models"
  13. "code.gitea.io/gitea/modules/auth"
  14. "code.gitea.io/gitea/modules/base"
  15. "code.gitea.io/gitea/modules/context"
  16. "code.gitea.io/gitea/modules/git"
  17. "code.gitea.io/gitea/modules/log"
  18. "code.gitea.io/gitea/modules/markup"
  19. "code.gitea.io/gitea/modules/markup/markdown"
  20. "code.gitea.io/gitea/modules/timeutil"
  21. "code.gitea.io/gitea/modules/util"
  22. wiki_service "code.gitea.io/gitea/services/wiki"
  23. )
  24. const (
  25. tplWikiStart base.TplName = "repo/wiki/start"
  26. tplWikiView base.TplName = "repo/wiki/view"
  27. tplWikiRevision base.TplName = "repo/wiki/revision"
  28. tplWikiNew base.TplName = "repo/wiki/new"
  29. tplWikiPages base.TplName = "repo/wiki/pages"
  30. )
  31. // MustEnableWiki check if wiki is enabled, if external then redirect
  32. func MustEnableWiki(ctx *context.Context) {
  33. if !ctx.Repo.CanRead(models.UnitTypeWiki) &&
  34. !ctx.Repo.CanRead(models.UnitTypeExternalWiki) {
  35. if log.IsTrace() {
  36. log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
  37. "User in repo has Permissions: %-+v",
  38. ctx.User,
  39. models.UnitTypeWiki,
  40. models.UnitTypeExternalWiki,
  41. ctx.Repo.Repository,
  42. ctx.Repo.Permission)
  43. }
  44. ctx.NotFound("MustEnableWiki", nil)
  45. return
  46. }
  47. unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki)
  48. if err == nil {
  49. ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
  50. return
  51. }
  52. }
  53. // PageMeta wiki page meta information
  54. type PageMeta struct {
  55. Name string
  56. SubURL string
  57. UpdatedUnix timeutil.TimeStamp
  58. }
  59. // findEntryForFile finds the tree entry for a target filepath.
  60. func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
  61. entries, err := commit.ListEntries()
  62. if err != nil {
  63. return nil, err
  64. }
  65. // The longest name should be checked first
  66. for _, entry := range entries {
  67. if entry.IsRegular() && entry.Name() == target {
  68. return entry, nil
  69. }
  70. }
  71. // Then the unescaped, shortest alternative
  72. var unescapedTarget string
  73. if unescapedTarget, err = url.QueryUnescape(target); err != nil {
  74. return nil, err
  75. }
  76. for _, entry := range entries {
  77. if entry.IsRegular() && entry.Name() == unescapedTarget {
  78. return entry, nil
  79. }
  80. }
  81. return nil, nil
  82. }
  83. func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
  84. wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath())
  85. if err != nil {
  86. ctx.ServerError("OpenRepository", err)
  87. return nil, nil, err
  88. }
  89. commit, err := wikiRepo.GetBranchCommit("master")
  90. if err != nil {
  91. return wikiRepo, nil, err
  92. }
  93. return wikiRepo, commit, nil
  94. }
  95. // wikiContentsByEntry returns the contents of the wiki page referenced by the
  96. // given tree entry. Writes to ctx if an error occurs.
  97. func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
  98. reader, err := entry.Blob().DataAsync()
  99. if err != nil {
  100. ctx.ServerError("Blob.Data", err)
  101. return nil
  102. }
  103. defer reader.Close()
  104. content, err := ioutil.ReadAll(reader)
  105. if err != nil {
  106. ctx.ServerError("ReadAll", err)
  107. return nil
  108. }
  109. return content
  110. }
  111. // wikiContentsByName returns the contents of a wiki page, along with a boolean
  112. // indicating whether the page exists. Writes to ctx if an error occurs.
  113. func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
  114. var entry *git.TreeEntry
  115. var err error
  116. pageFilename := wiki_service.NameToFilename(wikiName)
  117. if entry, err = findEntryForFile(commit, pageFilename); err != nil {
  118. ctx.ServerError("findEntryForFile", err)
  119. return nil, nil, "", false
  120. } else if entry == nil {
  121. return nil, nil, "", true
  122. }
  123. return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
  124. }
  125. func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  126. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  127. if err != nil {
  128. if !git.IsErrNotExist(err) {
  129. ctx.ServerError("GetBranchCommit", err)
  130. }
  131. return nil, nil
  132. }
  133. // Get page list.
  134. entries, err := commit.ListEntries()
  135. if err != nil {
  136. if wikiRepo != nil {
  137. wikiRepo.Close()
  138. }
  139. ctx.ServerError("ListEntries", err)
  140. return nil, nil
  141. }
  142. pages := make([]PageMeta, 0, len(entries))
  143. for _, entry := range entries {
  144. if !entry.IsRegular() {
  145. continue
  146. }
  147. wikiName, err := wiki_service.FilenameToName(entry.Name())
  148. if err != nil {
  149. if models.IsErrWikiInvalidFileName(err) {
  150. continue
  151. }
  152. if wikiRepo != nil {
  153. wikiRepo.Close()
  154. }
  155. ctx.ServerError("WikiFilenameToName", err)
  156. return nil, nil
  157. } else if wikiName == "_Sidebar" || wikiName == "_Footer" {
  158. continue
  159. }
  160. pages = append(pages, PageMeta{
  161. Name: wikiName,
  162. SubURL: wiki_service.NameToSubURL(wikiName),
  163. })
  164. }
  165. ctx.Data["Pages"] = pages
  166. // get requested pagename
  167. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  168. if len(pageName) == 0 {
  169. pageName = "Home"
  170. }
  171. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  172. ctx.Data["old_title"] = pageName
  173. ctx.Data["Title"] = pageName
  174. ctx.Data["title"] = pageName
  175. ctx.Data["RequireHighlightJS"] = true
  176. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  177. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  178. if noEntry {
  179. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  180. }
  181. if entry == nil || ctx.Written() {
  182. if wikiRepo != nil {
  183. wikiRepo.Close()
  184. }
  185. return nil, nil
  186. }
  187. sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
  188. if ctx.Written() {
  189. if wikiRepo != nil {
  190. wikiRepo.Close()
  191. }
  192. return nil, nil
  193. }
  194. footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
  195. if ctx.Written() {
  196. if wikiRepo != nil {
  197. wikiRepo.Close()
  198. }
  199. return nil, nil
  200. }
  201. metas := ctx.Repo.Repository.ComposeMetas()
  202. ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
  203. ctx.Data["sidebarPresent"] = sidebarContent != nil
  204. ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
  205. ctx.Data["footerPresent"] = footerContent != nil
  206. ctx.Data["footerContent"] = markdown.RenderWiki(footerContent, ctx.Repo.RepoLink, metas)
  207. // get commit count - wiki revisions
  208. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  209. ctx.Data["CommitCount"] = commitsCount
  210. return wikiRepo, entry
  211. }
  212. func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  213. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  214. if err != nil {
  215. if wikiRepo != nil {
  216. wikiRepo.Close()
  217. }
  218. if !git.IsErrNotExist(err) {
  219. ctx.ServerError("GetBranchCommit", err)
  220. }
  221. return nil, nil
  222. }
  223. // get requested pagename
  224. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  225. if len(pageName) == 0 {
  226. pageName = "Home"
  227. }
  228. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  229. ctx.Data["old_title"] = pageName
  230. ctx.Data["Title"] = pageName
  231. ctx.Data["title"] = pageName
  232. ctx.Data["RequireHighlightJS"] = true
  233. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  234. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  235. if noEntry {
  236. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  237. }
  238. if entry == nil || ctx.Written() {
  239. if wikiRepo != nil {
  240. wikiRepo.Close()
  241. }
  242. return nil, nil
  243. }
  244. ctx.Data["content"] = string(data)
  245. ctx.Data["sidebarPresent"] = false
  246. ctx.Data["sidebarContent"] = ""
  247. ctx.Data["footerPresent"] = false
  248. ctx.Data["footerContent"] = ""
  249. // get commit count - wiki revisions
  250. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  251. ctx.Data["CommitCount"] = commitsCount
  252. // get page
  253. page := ctx.QueryInt("page")
  254. if page <= 1 {
  255. page = 1
  256. }
  257. // get Commit Count
  258. commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page)
  259. if err != nil {
  260. if wikiRepo != nil {
  261. wikiRepo.Close()
  262. }
  263. ctx.ServerError("CommitsByFileAndRangeNoFollow", err)
  264. return nil, nil
  265. }
  266. commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
  267. commitsHistory = models.ParseCommitsWithSignature(commitsHistory)
  268. ctx.Data["Commits"] = commitsHistory
  269. pager := context.NewPagination(int(commitsCount), git.CommitsRangeSize, page, 5)
  270. pager.SetDefaultParams(ctx)
  271. ctx.Data["Page"] = pager
  272. return wikiRepo, entry
  273. }
  274. func renderEditPage(ctx *context.Context) {
  275. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  276. if err != nil {
  277. if wikiRepo != nil {
  278. wikiRepo.Close()
  279. }
  280. if !git.IsErrNotExist(err) {
  281. ctx.ServerError("GetBranchCommit", err)
  282. }
  283. return
  284. }
  285. defer func() {
  286. if wikiRepo != nil {
  287. wikiRepo.Close()
  288. }
  289. }()
  290. // get requested pagename
  291. pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  292. if len(pageName) == 0 {
  293. pageName = "Home"
  294. }
  295. ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
  296. ctx.Data["old_title"] = pageName
  297. ctx.Data["Title"] = pageName
  298. ctx.Data["title"] = pageName
  299. ctx.Data["RequireHighlightJS"] = true
  300. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  301. data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
  302. if noEntry {
  303. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  304. }
  305. if entry == nil || ctx.Written() {
  306. return
  307. }
  308. ctx.Data["content"] = string(data)
  309. ctx.Data["sidebarPresent"] = false
  310. ctx.Data["sidebarContent"] = ""
  311. ctx.Data["footerPresent"] = false
  312. ctx.Data["footerContent"] = ""
  313. }
  314. // Wiki renders single wiki page
  315. func Wiki(ctx *context.Context) {
  316. ctx.Data["PageIsWiki"] = true
  317. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  318. if !ctx.Repo.Repository.HasWiki() {
  319. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  320. ctx.HTML(200, tplWikiStart)
  321. return
  322. }
  323. wikiRepo, entry := renderViewPage(ctx)
  324. if ctx.Written() {
  325. if wikiRepo != nil {
  326. wikiRepo.Close()
  327. }
  328. return
  329. }
  330. defer func() {
  331. if wikiRepo != nil {
  332. wikiRepo.Close()
  333. }
  334. }()
  335. if entry == nil {
  336. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  337. ctx.HTML(200, tplWikiStart)
  338. return
  339. }
  340. wikiPath := entry.Name()
  341. if markup.Type(wikiPath) != markdown.MarkupName {
  342. ext := strings.ToUpper(filepath.Ext(wikiPath))
  343. ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext)
  344. }
  345. // Get last change information.
  346. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  347. if err != nil {
  348. ctx.ServerError("GetCommitByPath", err)
  349. return
  350. }
  351. ctx.Data["Author"] = lastCommit.Author
  352. ctx.HTML(200, tplWikiView)
  353. }
  354. // WikiRevision renders file revision list of wiki page
  355. func WikiRevision(ctx *context.Context) {
  356. ctx.Data["PageIsWiki"] = true
  357. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  358. if !ctx.Repo.Repository.HasWiki() {
  359. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  360. ctx.HTML(200, tplWikiStart)
  361. return
  362. }
  363. wikiRepo, entry := renderRevisionPage(ctx)
  364. if ctx.Written() {
  365. if wikiRepo != nil {
  366. wikiRepo.Close()
  367. }
  368. return
  369. }
  370. defer func() {
  371. if wikiRepo != nil {
  372. wikiRepo.Close()
  373. }
  374. }()
  375. if entry == nil {
  376. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  377. ctx.HTML(200, tplWikiStart)
  378. return
  379. }
  380. // Get last change information.
  381. wikiPath := entry.Name()
  382. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  383. if err != nil {
  384. ctx.ServerError("GetCommitByPath", err)
  385. return
  386. }
  387. ctx.Data["Author"] = lastCommit.Author
  388. ctx.HTML(200, tplWikiRevision)
  389. }
  390. // WikiPages render wiki pages list page
  391. func WikiPages(ctx *context.Context) {
  392. if !ctx.Repo.Repository.HasWiki() {
  393. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  394. return
  395. }
  396. ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
  397. ctx.Data["PageIsWiki"] = true
  398. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  399. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  400. if err != nil {
  401. if wikiRepo != nil {
  402. wikiRepo.Close()
  403. }
  404. return
  405. }
  406. entries, err := commit.ListEntries()
  407. if err != nil {
  408. if wikiRepo != nil {
  409. wikiRepo.Close()
  410. }
  411. ctx.ServerError("ListEntries", err)
  412. return
  413. }
  414. pages := make([]PageMeta, 0, len(entries))
  415. for _, entry := range entries {
  416. if !entry.IsRegular() {
  417. continue
  418. }
  419. c, err := wikiRepo.GetCommitByPath(entry.Name())
  420. if err != nil {
  421. if wikiRepo != nil {
  422. wikiRepo.Close()
  423. }
  424. ctx.ServerError("GetCommit", err)
  425. return
  426. }
  427. wikiName, err := wiki_service.FilenameToName(entry.Name())
  428. if err != nil {
  429. if models.IsErrWikiInvalidFileName(err) {
  430. continue
  431. }
  432. if wikiRepo != nil {
  433. wikiRepo.Close()
  434. }
  435. ctx.ServerError("WikiFilenameToName", err)
  436. return
  437. }
  438. pages = append(pages, PageMeta{
  439. Name: wikiName,
  440. SubURL: wiki_service.NameToSubURL(wikiName),
  441. UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
  442. })
  443. }
  444. ctx.Data["Pages"] = pages
  445. defer func() {
  446. if wikiRepo != nil {
  447. wikiRepo.Close()
  448. }
  449. }()
  450. ctx.HTML(200, tplWikiPages)
  451. }
  452. // WikiRaw outputs raw blob requested by user (image for example)
  453. func WikiRaw(ctx *context.Context) {
  454. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  455. if err != nil {
  456. if wikiRepo != nil {
  457. return
  458. }
  459. }
  460. providedPath := ctx.Params("*")
  461. var entry *git.TreeEntry
  462. if commit != nil {
  463. // Try to find a file with that name
  464. entry, err = findEntryForFile(commit, providedPath)
  465. if err != nil {
  466. ctx.ServerError("findFile", err)
  467. return
  468. }
  469. if entry == nil {
  470. // Try to find a wiki page with that name
  471. if strings.HasSuffix(providedPath, ".md") {
  472. providedPath = providedPath[:len(providedPath)-3]
  473. }
  474. wikiPath := wiki_service.NameToFilename(providedPath)
  475. entry, err = findEntryForFile(commit, wikiPath)
  476. if err != nil {
  477. ctx.ServerError("findFile", err)
  478. return
  479. }
  480. }
  481. }
  482. if entry != nil {
  483. if err = ServeBlob(ctx, entry.Blob()); err != nil {
  484. ctx.ServerError("ServeBlob", err)
  485. }
  486. return
  487. }
  488. ctx.NotFound("findEntryForFile", nil)
  489. }
  490. // NewWiki render wiki create page
  491. func NewWiki(ctx *context.Context) {
  492. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  493. ctx.Data["PageIsWiki"] = true
  494. ctx.Data["RequireSimpleMDE"] = true
  495. if !ctx.Repo.Repository.HasWiki() {
  496. ctx.Data["title"] = "Home"
  497. }
  498. ctx.HTML(200, tplWikiNew)
  499. }
  500. // NewWikiPost response for wiki create request
  501. func NewWikiPost(ctx *context.Context, form auth.NewWikiForm) {
  502. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  503. ctx.Data["PageIsWiki"] = true
  504. ctx.Data["RequireSimpleMDE"] = true
  505. if ctx.HasError() {
  506. ctx.HTML(200, tplWikiNew)
  507. return
  508. }
  509. if util.IsEmptyString(form.Title) {
  510. ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplWikiNew, form)
  511. return
  512. }
  513. wikiName := wiki_service.NormalizeWikiName(form.Title)
  514. if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil {
  515. if models.IsErrWikiReservedName(err) {
  516. ctx.Data["Err_Title"] = true
  517. ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
  518. } else if models.IsErrWikiAlreadyExist(err) {
  519. ctx.Data["Err_Title"] = true
  520. ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), tplWikiNew, &form)
  521. } else {
  522. ctx.ServerError("AddWikiPage", err)
  523. }
  524. return
  525. }
  526. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
  527. }
  528. // EditWiki render wiki modify page
  529. func EditWiki(ctx *context.Context) {
  530. ctx.Data["PageIsWiki"] = true
  531. ctx.Data["PageIsWikiEdit"] = true
  532. ctx.Data["RequireSimpleMDE"] = true
  533. if !ctx.Repo.Repository.HasWiki() {
  534. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  535. return
  536. }
  537. renderEditPage(ctx)
  538. if ctx.Written() {
  539. return
  540. }
  541. ctx.HTML(200, tplWikiNew)
  542. }
  543. // EditWikiPost response for wiki modify request
  544. func EditWikiPost(ctx *context.Context, form auth.NewWikiForm) {
  545. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  546. ctx.Data["PageIsWiki"] = true
  547. ctx.Data["RequireSimpleMDE"] = true
  548. if ctx.HasError() {
  549. ctx.HTML(200, tplWikiNew)
  550. return
  551. }
  552. oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  553. newWikiName := wiki_service.NormalizeWikiName(form.Title)
  554. if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
  555. ctx.ServerError("EditWikiPage", err)
  556. return
  557. }
  558. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName))
  559. }
  560. // DeleteWikiPagePost delete wiki page
  561. func DeleteWikiPagePost(ctx *context.Context) {
  562. wikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
  563. if len(wikiName) == 0 {
  564. wikiName = "Home"
  565. }
  566. if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil {
  567. ctx.ServerError("DeleteWikiPage", err)
  568. return
  569. }
  570. ctx.JSON(200, map[string]interface{}{
  571. "redirect": ctx.Repo.RepoLink + "/wiki/",
  572. })
  573. }