Template:Short description Template:Use mdy dates
Carrie is a 1976 American supernatural horror film directed by Brian De Palma from a screenplay written by Lawrence D. Cohen, adapted from Stephen King's 1974 epistolary novel of the same name. The film stars Sissy Spacek as Carrie White, a diffident 16-year-old who is consistently mocked and bullied at school. Her peers are unaware that she possesses telekinetic powers. The film also featured Piper Laurie, Amy Irving, Nancy Allen, William Katt, P. J. Soles, Betty Buckley, and John Travolta in supporting roles. It is the first film in the Carrie franchise.
The film was based on King's first novel by the same name. De Palma was intrigued by the story and pushed for the studio to direct it while Spacek was encouraged by her husband to audition. It is the first of more than 100 film and television productions adapted from, or based on, the published works of King.
Carrie was theatrically released on November 3, 1976, by United Artists. The film became a critical and commercial success, grossing over $33.8 million against its $1.8 million budget. It received two nominations at the 49th Academy Awards: Best Actress (for Spacek) and Best Supporting Actress (for Laurie). It is widely cited by critics and audience members alike as the best adaptation of the novel amongst the numerous films and television shows based on the character, as well as one of the best films based on King's publications. The film has had a significant influence on popular culture.[3] Several publications have regarded it as one of the greatest horror films ever made. In 2008, Carrie was ranked 86th on Empire's list of The 500 Greatest Movies of All Time.[4] It was ranked 15th on Entertainment Weekly's list of the 50 Best High School Movies, and 46th on the American Film Institute list AFI's 100 Years...100 Thrills. The film's prom scene has had a major influence on popular culture and was ranked eighth on Bravo's 2004 program The 100 Scariest Movie Moments.[5]
Plot[]
Carrie White is a shy 16-year-old girl who lives with her fanatically religious mother Margaret. Carrie is unpopular at school and is often ostracized by her peers. When Carrie experiences her first period in the school shower, she panics because she was never told of this process. Carrie's classmates humiliate her by throwing tampons and chanting "Plug it up" until the gym teacher, Miss Collins, intervenes. Following conversations with Miss Collins and the principal, Carrie is dismissed from school. After arriving home, Margaret considers Carrie's menstruation to be a manifestation of sinful sexual fantasies, and she locks Carrie in an altar-like "prayer closet" to pray for forgiveness. At school, Collins reprimands Carrie's tormentors and punishes them with a week-long after-school detention in gym class. Those who skip the punitive measure are suspended for three days and banned from the upcoming prom. Christine "Chris" Hargensen, a wealthy, popular girl who is Carrie's longtime bully and the leader of Carrie's classmates, walks out.
Chris plots vengeance against Carrie with her boyfriend Billy Nolan and her best friend Norma. They break into a local farm and kill pigs to drain their blood into a bucket, which they place above the school's main stage in the gymnasium. Norma, a prominent figure in the school's student council regime, plans to rig the Prom Queen election in Carrie's favor to get her on the stage. Meanwhile, Sue Snell, a deeply remorseful classmate, asks her handsome and popular boyfriend, Tommy Ross, to invite Carrie to prom. Carrie initially thinks the proposition is a prank, but he insists that it is genuine and she reluctantly accepts after being consoled by Miss Collins. Back at home, she begins to discover that she has the power of telekinesis as she shakes off her shyness. In spite of Margaret's cries of protest that Tommy is using her, Carrie puts on a flattering dress and hairstyle for the prom. Margaret sees Carrie's telekinetic powers and denounces her as a witch before Carrie leaves with Tommy.
During the prom, Chris and Billy hide under the stage while the other conspirators switch the ballots to ensure that Carrie wins the Prom Queen title. As Carrie stands onstage with Tommy, finally beginning to feel accepted by her peers, Chris pulls the rope attached to the bucket of pig blood and douses her. The empty bucket hits Tommy in the head, knocking him unconscious, and the crowd is left shocked and speechless at the prank as Chris and Billy sneak out. Carrie begins to hallucinate that everyone is mocking her, remembering her mother's claim that "they're all gonna laugh at you." In a sudden fit of rage, she uses her telekinesis to seal the exits from the gym and set it on fire, killing most of the attendees. Sue survives, having been thrown out of the prom by Miss Collins earlier, but watches as the students and teachers die. As Carrie walks home, Chris and Billy attempt to run her over with Billy's car, but Carrie senses their presence and kills them by causing their car to overturn and explode.
As Carrie scrubs herself clean at home, Margaret reveals that she was conceived after a rape by her drunken father, an act that Margaret shamefully admits she enjoyed. Saying that "sin never dies," Margaret comforts Carrie, then stabs her in the back with a kitchen knife and begins to chase her through the house. Carrie levitates several sharp implements and sends them flying toward Margaret, pinning her to a doorway and crucifying her. Carrie then incinerates the house with them still inside.
Some time later, Sue - the only survivor of the prom - struggles to deal with the trauma she has experienced. She has a nightmare in which she lays flowers on the charred remains of Carrie's home, with a "for sale" sign vandalized in red paint with the phrase "Carrie White burns in Hell!" Suddenly, Carrie's bloody arm reaches from beneath the rubble and grabs Sue's forearm. Sue wakes up screaming as her mother comforts her.
Cast[]
Template:Div col
- Sissy Spacek as Carrie White
- Piper Laurie as Margaret White
- Amy Irving as Sue Snell
- William Katt as Tommy Ross
- Betty Buckley as Miss Collins
- Nancy Allen as Chris Hargensen
- John Travolta as Billy Nolan
- P. J. Soles as Norma Watson
- Sydney Lassick as Mr. Fromm
- Stefan Gierasch as Principal Morton
- Priscilla Pointer as Eleanor Snell
- Edie McClurg as Helen Shyres
- Michael Talbott as Freddy
- Cindy Daly as Cora
- Deirdre Berthrong as Rhonda
- Harry Gold as George
- Noelle North as Frieda
- Doug Cox as The Beak
- Anson Downes as Ernest
Template:Div col end
Production[]
Template:Expand section
Development[]
Carrie was the first Stephen King novel to be published and the first to be adapted into a feature film.[6] In an interview in Port Charlotte, Florida at a public appearance near his home on the Gulf coast on March 20, 2010, King said he was 26 years old at the time and was paid just $2,500 for the film rights, but added, "I was fortunate to have that happen to my first book."[7] De Palma told Cinefantastique magazine in an interview in 1977:
- “I read the book. It was suggested to me by a writer friend of mine. A writer friend of his, Stephen King, had written it. I guess this was almost two years ago [circa 1975]. I liked it a lot and proceeded to call my agent to find out who owned it. I found out that nobody had bought it yet. A lot of studios were considering it, so I called around to some of the people I knew and said it was a terrific book and I'm very interested in doing it. Then nothing happened for, I guess, six months.[8]”
- ―{{{2}}}
Lawrence D. Cohen was hired as the screenwriter, and produced the first draft, which had closely followed the novel's intentions.[9] United Artists accepted the second draft but only allocated De Palma a budget of $1.6 million, a small amount considering the popularity of horror films at the time. The budget eventually rose to $1.8 million.[10] Certain scripted scenes were omitted from the final version, mainly due to financial limitations.[11][12]
Casting[]
Many young actresses auditioned for the lead role, including Melanie Griffith. Sissy Spacek was persuaded by husband Jack Fisk to audition for the title role. Fisk then convinced De Palma to let her audition, and she read for all of the parts. De Palma's first choice for the role of Carrie was Betsy Slade, who received good notices for her role in the film Our Time (1974). Determined to land the leading role, Spacek backed out of a television commercial she was scheduled to film,[13] rubbed Vaseline into her hair, left her face unwashed, and arrived for her screen test clad in a sailor dress which her mother had made her in the seventh grade, with the hem cut off,[8] and was given the part.
Nancy Allen was the last to audition, and her audition came just as she was on the verge of leaving Hollywood.[9] She and De Palma later married.[14]
Filming[]
De Palma began with director of photography Isidore Mankofsky, who was eventually replaced by Mario Tosi after conflict between Mankofsky and De Palma ensued.[15] Gregory M. Auer, assisted by Ken Pepiot,[16] served as the special effects supervisor for Carrie, with Jack Fisk, Spacek's husband, as art director.
The White house was filmed in Santa Paula, California. To give the house a Gothic theme, the director and producers visited religious souvenir shops to find artifacts to decorate the set location.[17]
A wraparound segment at the beginning and end of the film was scripted and filmed, which featured the Whites' home being pummeled by stones that hailed from the sky. The opening scene was filmed as planned, though on celluloid, the tiny pebbles looked like rain water.[9] A mechanical malfunction botched filming the night when the model of the Whites' home was set to be destroyed by stones, so the filmmakers burned it down instead and deleted the scenes with the stones altogether. The original opening scene is presumed lost.[9]
The final scene, in which Sue reaches toward Carrie's grave, was shot backwards to give it a dreamlike quality. This scene was inspired by the final scene in Deliverance (1972).[9] Rather than let a stunt double perform the scene underground, Spacek insisted on using her own hand in the scene, so she was positioned under the rocks and gravel. De Palma explains that crew members "had to bury her. Bury her! We had to put her in a box and stick her underneath the ground. Well, I had her husband [Fisk] bury her because I certainly didn't want to bury her."[9]
Music[]
The score for Carrie was composed by Pino Donaggio. In addition, Donaggio scored two pop songs ("Born to Have It All" and "I Never Dreamed Someone Like You Could Love Someone Like Me") with lyrics by Merrit Malloy for the early portion of the prom sequence. These songs were performed by Katie Irving (sister of Amy Irving and daughter of Priscilla Pointer). Donaggio would work again with De Palma on Home Movies, Dressed to Kill, Blow Out, Body Double, Raising Cain, Passion, and Domino.
The soundtrack album was originally released on vinyl in 1976 from United Artists Records.[18] A deluxe CD edition containing a few tracks of dialogue from the film was released by Rykodisc in 1997, and a 2005 CD re-release of the original soundtrack (minus dialogue) was available from Varèse Sarabande.[19] In 2010, Kritzerland Records released all 35 cues of Donaggio's score for the film on a two-disc CD set which was presented as the complete score. Also included in this edition were the versions of "Born to Have It All" and "I Never DreamedTemplate:Nbsp..."which were heard in the film, as well as instrumentals of both songs, and hidden at the end of the final track, a version of the "Calisthenics" cue with Betty Buckley's studio-recorded voice-over from the detention scene. The second disc was a remastered copy of the original 13-track album. The Kritzerland release was a limited edition of 1,200 copies. Kritzerland rereleased the first disc as "The Encore Edition" in February 2013; this release was limited to 1,000 copies.[20]
Release[]
The film opened November 3, 1976 in 17 theaters in the Washington D.C.-Baltimore area. Two days later it opened in 9 theaters in Chicago, before opening in 53 theaters in New York City on November 16 and in Los Angeles on November 17.[21][22]
Reception and legacy[]
Carrie received widespread critical acclaim and was cited as one of the best films of the year.[23][24][25] The review aggregator Rotten Tomatoes gives the film an approval rating of 92% based on 66 reviews, with an average rating of 8.3/10. The website's critical consensus reads, "Carrie is a horrifying look at supernatural powers, high school cruelty, and teen angst—and it brings us one of the most memorable and disturbing prom scenes in history."[26] On Metacritic, which assigns a normalized rating based on reviews, the film has a weighted average score of 85 out of 100, based on 14 critics.[27]
Roger Ebert of the Chicago Sun-Times stated the film was an "absolutely spellbinding horror movie", as well as an "observant human portrait", giving three and a half stars out of four.[28] Pauline Kael of The New Yorker stated that Carrie was "the best scary-funny movie since Jaws—a teasing, terrifying, lyrical shocker." Take One Magazine critic Susan Schenker said she was "angry at the way Carrie manipulated me to the point where my heart was thudding, and embarrassed because the film really works."[29] A 1998 edition of The Movie Guide stated Carrie was a "landmark horror film", while Stephen Farber prophetically stated in a 1978 issue of New West Magazine, "it's a horror classic, and years from now it will still be written and argued about, and it will still be scaring the daylights out of new generations of moviegoers."[30] Quentin Tarantino placed Carrie at number 8 in a list of his favorite films ever.[31]
In a 2010 interview, King replied that he thought, although dated now, Carrie was a "good movie."[7]
Nevertheless, the film was not without its detractors. Andrew Sarris of The Village Voice commented, "There are so few incidents that two extended sequences are rendered in slow-motion as if to pad out the running timeTemplate:Nbsp..."[30] Gene Siskel of the Chicago Tribune gave the film two-and-a-half stars out of four and called it "a crude shocker with a little style," praising the "strong performances" but opining that the movie "falls apart" during the climax which he described as "crude and sloppy."[32]
Template:Anchor
Box office[]
Carrie was a box office success earning $14.5 million in theatrical rentals in the United States and Canada by January 1978[33][34] from a gross of $33.8 million.[2] In its first 19 days from 60 markets, the film had grossed $3,882,827.[21] Overseas, the film earned rentals of $7 million for a worldwide total of $22 million.[35]
Accolades[]
Carrie is one of the few horror films to be nominated for multiple Academy Awards. Spacek and Laurie received nominations for Best Actress and Best Supporting Actress awards, respectively. The film also won the grand prize at the Avoriaz Fantastic Film Festival, while Spacek was given the Best Actress award by the National Society of Film Critics. In 2008, Carrie was ranked number 86 on Empire Magazine's list of The 500 Greatest Movies of All Time.[4] The movie also ranked number 15 on the Entertainment Weekly list of the 50 Best High School Movies, and No. 46 on the American Film Institute's list of 100 Greatest Cinema Thrills, and was also ranked eighth for its ending sequence on Bravo's The 100 Scariest Movie Moments (2004).[5]
Award | Category | Recipient | Result |
---|---|---|---|
49th Academy Awards | Best Actress | Sissy Spacek | Template:Nom |
Best Supporting Actress | Piper Laurie | Template:Nom | |
Avoriaz Fantastic Film Festival | Grand Prize | Brian De Palma | Template:Won |
Special Mention | Sissy Spacek | Template:Won | |
Edgar Allan Poe Awards | Best Motion Picture | Paul Monash | Template:Nom |
34th Golden Globe Awards | Best Supporting Actress – Motion Picture | Piper Laurie | Template:Nom |
Hugo Awards | Best Dramatic Presentation | Brian De Palma, Lawrence D. Cohen and Stephen King |
Template:Nom |
New York Film Critics Circle | Best Actress | Sissy Spacek | Template:Nom |
National Society of Film Critics | Best Actress | Template:Won | |
4th Saturn Awards | Best Horror Film | Paul Monash | Template:Nom |
- AFI's 100 Years ... 100 Thrills – #46[36]
- AFI's 100 Years ... 100 Heroes and Villains – Carrie White – Nominated Villain[37]
Related productions[]
- Main article: Carrie (franchise)
Carrie, along with the novel, has been reproduced and adapted several times.
Sequel[]
- Main article: The Rage: Carrie 2
The Rage: Carrie 2 was released in 1999. It featured another teenager with telekinetic powers who is revealed to have shared a father with Carrie White. The film received universally negative reviews and was a box office failure. Amy Irving reprises her role of Sue Snell from the previous film.
2002 television film[]
- Main article: Carrie (2002 film)
In 2002, a television film based on King's novel and starring Angela Bettis in the titular role was released. The film updated the events of the story to modern-day settings and technology while simultaneously attempting to be more faithful to the book's original structure, storyline, and specific events. However, the ending was drastically changed: instead of killing her mother and then herself, the film has Carrie killing her mother, being revived via CPR by Sue Snell and being driven to Florida to hide. This new ending marked a complete divergence from the novel and was a signal that the film served as a pilot for a Carrie television series, which never materialized. In the new ending, the rescued Carrie vows to help others with similar gifts to her own. Although Bettis' portrayal of Carrie was highly praised, the film was cited by most critics as inferior to the original.[38]
2013 film[]
- Main article: Carrie (2013 film)
In May 2011, Metro-Goldwyn-Mayer and Screen Gems announced that Carrie would be adapted to film once more.[39] Playwright Roberto Aguirre-Sacasa wrote the script as "a more faithful adaptation" of King's novel but shared a screenplay credit with the 1976 film's writer Lawrence D. Cohen. Aguirre-Sacasa had previously adapted King's epic novel The Stand into comic-book form in 2008.
The role of Carrie was played by 16-year-old actress Chloë Grace Moretz.[40] Julianne Moore starred as Carrie's mother Margaret White, and Gabriella Wilde as Sue Snell.[41] Alex Russell and Broadway actor Ansel Elgort played Billy Nolan and Tommy Ross respectively.[42] Portia Doubleday was given the role of Chris Hargensen and Judy Greer was cast as Miss Desjardin.[43]
Kimberly Peirce, known for her work on Boys Don't Cry, directed the new adaptation.[44] It was released on October 18, 2013, and received mixed reviews.
Stage productions[]
- Main article: Carrie (musical)
A 1988 Broadway musical of the same name, based on King's novel and starring Betty Buckley, Linzi Hateley, and Darlene Love, closed after only sixteen previews and five performances. An English pop opera filtered through Greek tragedy, the show was so notorious that it provided the title to Ken Mandelbaum's survey of theatrical disasters, Not Since Carrie: Forty Years of Broadway Musical Flops.[45]
Early in the 21st century, playwright Erik Jackson attempted to secure the rights to stage another production of Carrie the musical, but his request was rejected. Jackson eventually earned the consent of King[46] to mount a new, officially sanctioned, non-musical production of Carrie, which debuted Off-Broadway in 2006 with drag queen Sherry Vine in the lead role.[47] Similarly, many other unofficial spoofs have been staged over the years, usually with a gym teacher named "Miss Collins" (as opposed to the novel's "Miss Desjardin" and the musical's "Miss Gardner"), most notably the "parodage" Scarrie the Musical,[48] which hit the Illinois stage in 1998 and was revived in 2005; Dad's Garage Theatre's 2002 production of Carrie White the Musical;[49] and the 2007 New Orleans production of Carrie's Facts of Life,[50] which was a hybrid of Carrie and the classic American sitcom The Facts of Life. A high school production of the musical is the focus of "Chapter Thirty-One: A Night to Remember" episode of Riverdale.[51]
Home media[]
Carrie was originally released on VHS and LaserDisc formats, for which it received numerous editions throughout the world.
In the United States and Canada, Carrie has been made available several times on DVD format from MGM Home Entertainment, debuting on September 29, 1998,[52] while a "Special Edition" set was released on August 28, 2001.[53] On December 4, 2007, the film was released a part of MGM's "Decades Collection," which included a soundtrack CD.[54] The film was additionally released within multiple sets via MGM; first with Carrie, The Rage: Carrie 2, and Carrie (the 2002 television film) on January 18, 2011,[55] and the second, as part of MGM's 90th anniversary, featured with Misery and The Silence of the Lambs.[55]
The film was released for the first time on Blu-ray in the U.S. and Canada from MGM on October 7, 2008, which contained an MPEG-2 codec, with new DTS-HD 5.1 Master Lossless Audio, while retaining the original English Mono, and included Spanish Audio and French 5.1 Dolby Surround. The only special feature on the set is a theatrical trailer.[56] The film was again released on Blu-ray on July 18, 2013, when it was available exclusively through Comic-Con in San Diego from MGM and FoxConnect, containing a slipcover with exclusive artwork.[57] Two further editions were made available from MGM in 2014; a "Carrie 2-Pack" set containing the original film and the 2013 adaptation, released September 9, 2014,[58] and finally, a re-issue Blu-ray with a collectible Halloween faceplate, on October 21, 2014.[59] Home distribution rights are currently held by Shout Factory, and the film was released via their subsidiary label, Scream Factory on October 11, 2016, in a two-disc "Collector's Edition," now available with MPEG-4 coding, and a new 4K scan. Special features on the set include the theatrical trailer, Carrie franchise trailer gallery, new interviews with writer Lawrence D. Cohen, editor Paul Hirsch, actors Piper Laurie, P.J. Soles, Nancy Allen, Betty Buckley, William Katt, and Edie McClurg, casting director Harriet B. Helberg, director of photography Mario Tosi, and composer Pino Donaggio, "Horror's Hallowed Grounds" – Revisiting the Film's Original Locations, "Acting Carrie" featurette, "Visualizing Carrie" featurette, a look at "Carrie the Musical," TV spots, radio spots, still gallery, "Stephen King and the Evolution of Carrie" text gallery. The set also includes reversible sleeve containing original artwork and newly commissioned artwork from Shout Factory, and a slipcover containing the new artwork.[60] On October 11, 2016, Shout Factory additionally released a "Deluxe Limited Edition" of 2000 copies, which includes the slipcover contained in the "Collector's Edition," with an additional poster matching the slipcover, and an alternative slipcover and poster consisting of different artwork.[61] In the United Kingdom, the film received its initial DVD release on February 1, 2000, via MGM. A reissue "Special Edition" DVD was made available from MGM on October 22, 2001,[62] while a two-disc standard set was released on September 7, 2006.[63] A DVD set, "The Carrie Collection," consisting of both the original film, and The Rage: Carrie 2, was released from 20th Century Fox Home Entertainment on October 7, 2013,[64] while on the same day, a reissue DVD containing newly commissioned artwork,[65] as well as the first-ever Blu-ray release in the UK was made available from 20th Century Fox.[66] A second Blu-ray edition became available in the form of a steelbook, released on September 29, 2014; a set which reverted to the previous-style artwork.[67]
On September 22, 2017, it was announced that Carrie would receive a "Limited Collector's Edition" Blu-ray of 5,000 copies from Arrow Films, providing the definitive release of the film. The set contained a new 4K restoration, with special features, including commentary by authors Lee Gambin and Alexandra Heller-Nicholas, recorded exclusively for the release; brand-new visual essay comparing the various versions and adaptations of Carrie; "Acting Carrie" featurette, "More Acting Carrie" featurette; "Writing Carrie," an interview with writer Lawrence D. Cohen/"Shooting Carrie," an interview with cinematographer Mario Tosi; "Cutting Carrie," an interview with editor Paul Hirsch/"Casting Carrie," an interview with casting director Harriet B. Helberg; "Bucket of Blood," an interview with composer Pino Donaggio; "Horror's Hallowed Grounds," a look back at the film's locations, gallery, trailer, TV spots, radio spots; Carrie trailer reel; and 60-page limited-edition booklet featuring new writing on the film by author Neil Mitchell, alongside reversible artwork, poster and art cards. The set was released on December 11, 2017.[68][69]
On most of the later VHS releases and DVD sets, John Travolta's name was included on the artwork alongside Sissy Spacek. Although Travolta only appeared in a minor supporting role in the film, his name was featured to capitalize on his high-profile career in his many films following Carrie, therefore possibly increasing sales.
References[]
- ↑ CARRIE (X). United Artists. British Board of Film Classification (November 4, 1976). Retrieved on June 20, 2014.
- ↑ 2.0 2.1 Carrie, Box Office Information. Retrieved on January 15, 2020.
- ↑ Carrie Movie Review – Stephen King's Teen Horror Classic Carrie – the Movie. Classicfilm.about.com (April 10, 2012). Retrieved on October 2, 2012.
- ↑ 4.0 4.1 Empire's 500 Greatest Movies of All Time. Empire (December 5, 2006). Retrieved on October 2, 2012.
- ↑ 5.0 5.1 The 100 Scariest Movie Moments. bravotv.com. Archived from the original on July 19, 2006. Retrieved on August 6, 2006.
- ↑ "How Carrie Changed Stephen King's Life, and Began a Generation of Horror", April 4, 2014.
- ↑ 7.0 7.1 Stetson, Nancy (March 25–31, 2010). "King rules The Big read for a day in Port Charlotte". Florida Weekly: B8. Newspaper column review of a live interview by Christy Arnold of King onstage at the Cultural Center of Charlotte County, Florida, March 20, 2010: "Although the film "Carrie" is dated now, he said he thought it was a good movie. 'I was fortunate to have that happen to my first book.' (He was 26 years old and was paid $2,500, he said.)"
- ↑ 8.0 8.1 Brian De Palma interview (July 1977). Retrieved 30 June 2010.
- ↑ 9.0 9.1 9.2 9.3 9.4 9.5 Template:Cite video
- ↑ Neil Mitchell (5 August 2014). Carrie. Auteur Publishing, page 31. ISBN 978-1-906733-92-6.
- ↑ "How Carrie: the Growing Pains of a Horror Classic", November 26, 2013.
- ↑ Sissy Spacek Interviews – Cult Oddities. Retrieved on September 13, 2017.
- ↑ Template:Cite video
- ↑ "7 Months Enough for DePalma, Wife", April 28, 1996.
- ↑ Brian De Palma.net. Retrieved May 27, 2007. --[[ ---------------------------------- Lua module implementing the Template loop detected: Template:Webarchive template. A merger of the functionality of three templates: Template:Wayback, Template:Webcite and Template:Cite archives ]] --[[--------------------------< D E P E N D E N C I E S >------------------------------------------------------ ]] require('Module:No globals'); local getArgs = require ('Module:Arguments').getArgs; --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- ]] local categories = {}; -- category names local config = {}; -- global configuration settings local digits = {}; -- for i18n; table that translates local-wiki digits to western digits local err_warn_msgs = {}; -- error and warning messages local excepted_pages = {}; local month_num = {}; -- for i18n; table that translates local-wiki month names to western digits local prefixes = {}; -- service provider tail string prefixes local services = {}; -- archive service provider data from local s_text = {}; -- table of static text strings used to build final rendering local uncategorized_namespaces = {}; -- list of namespaces that we should not categorize local uncategorized_subpages = {}; -- list of subpages that should not be categorized --[[--------------------------< P A G E S C O P E I D E N T I F I E R S >---------------------------------- ]] local non_western_digits; -- boolean flag set true when data.digits.enable is true local this_page = mw.title.getCurrentTitle(); local track = {}; -- Associative array to hold tracking categories local ulx = {}; -- Associative array to hold template data --[[--------------------------< S U B S T I T U T E >---------------------------------------------------------- Populates numbered arguments in a message string using an argument table. ]] local function substitute (msg, args) return args and mw.message.newRawMessage (msg, args):plain() or msg; end --[[--------------------------< tableLength >----------------------- Given a 1-D table, return number of elements ]] local function tableLength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end --[=[-------------------------< M A K E _ W I K I L I N K >---------------------------------------------------- Makes a wikilink; when both link and display text is provided, returns a wikilink in the form D; if only link is provided, returns a wikilink in the form L; if neither are provided or link is omitted, returns an empty string. ]=] local function make_wikilink (link, display, no_link) if nil == no_link then if link and ( ~= link) then if display and ( ~= display) then return table.concat ({'', display, ''}); else return table.concat ({'', link, ''}); end end return display or ; -- link not set so return the display text else -- no_link if display and ( ~= display) then -- if there is display text return display; -- return that else return link or ; -- return the target article name or empty string end end end --[[--------------------------< createTracking >----------------------- Return data in track[] ie. tracking categories ]] local function createTracking() if not excepted_pages[this_page.fullText] then -- namespace:title/fragment is allowed to be categorized (typically this module's / template's testcases page(s)) if uncategorized_namespaces[this_page.nsText] then return ; -- this page not to be categorized so return empty string end for _,v in ipairs (uncategorized_subpages) do -- cycle through page name patterns if this_page.text:match (v) then -- test page name against each pattern return ; -- this subpage type not to be categorized so return empty string end end end local out = {}; if tableLength(track) > 0 then for key, _ in pairs(track) do -- loop through table table.insert (out, make_wikilink (key)); -- and convert category names to links end end return table.concat (out); -- concat into one big string; empty string if table is empty end --[[--------------------------< inlineError >----------------------- Critical error. Render output completely in red. Add to tracking category. This function called as the last thing before abandoning this module ]] local function inlineError (msg, args) track[categories.error] = 1 return table.concat ({ 'Error in ', -- open the error message span config.tname, -- insert the local language template name ' template: ', substitute (msg, args), -- insert the formatted error message '.', -- close the span createTracking() -- add the category }) end --[[--------------------------< inlineRed >----------------------- Render a text fragment in red, such as a warning as part of the final output. Add tracking category. ]] local function inlineRed(msg, trackmsg) if trackmsg == "warning" then track[categories.warning] = 1; elseif trackmsg == "error" then track[categories.error] = 1; end return '' .. msg .. '' end --[[--------------------------< base62 >----------------------- Convert base-62 to base-10 Credit: https://de.wikipedia.org/wiki/Modul:Expr ]] local function base62( value ) local r = 1 -- default return value is input value is malformed if value:match ('%W') then -- value must only be in the set [0-9a-zA-Z] return; -- nil return when value contains extraneous characters end local n = #value -- number of characters in value local k = 1 local c r = 0 for i = n, 1, -1 do -- loop through all characters in value from ls digit to ms digit c = value:byte( i, i ) if c >= 48 and c <= 57 then -- character is digit 0-9 c = c - 48 elseif c >= 65 and c <= 90 then -- character is ascii a-z c = c - 55 else -- must be ascii A-Z c = c - 61 end r = r + c * k -- accumulate this base62 character's value k = k * 62 -- bump for next end -- for i return r end --[[--------------------------< D E C O D E _ D A T E >-------------------------------------------------------- Given a date string, return it in iso format along with an indicator of the date's format. Except that month names must be recognizable as legitimate month names with proper capitalization, and that the date string must match one of the recognized date formats, no error checking is done here; return nil else ]] local function decode_date (date_str) local patterns = { ['dmy'] = {'^(%d%d?) +([^%s%d]+) +(%d%d%d%d)$', 'd', 'm', 'y'}, -- %a does not recognize unicode combining characters used by some languages ['mdy'] = {'^([^%s%d]+) (%d%d?), +(%d%d%d%d)$', 'm', 'd', 'y'}, ['ymd'] = {'^(%d%d%d%d) +([^%s%d]+) (%d%d?)$', 'y', 'm', 'd'}, -- not mos compliant at en.wiki but may be acceptible at other wikis }; local t = {}; if non_western_digits then -- this wiki uses non-western digits? date_str = mw.ustring.gsub (date_str, '%d', digits); -- convert this wiki's non-western digits to western digits end if date_str:match ('^%d%d%d%d%-%d%d%-%d%d$') then -- already an iso format date, return western digits form return date_str, 'iso'; end for k, v in pairs (patterns) do local c1, c2, c3 = mw.ustring.match (date_str, patterns[k][1]); -- c1 .. c3 are captured but we don't know what they hold if c1 then -- set on match t = { -- translate unspecified captures to y, m, and d [patterns[k][2]] = c1, -- fill the table of captures with the captures [patterns[k][3]] = c2, -- take index names from src_pattern table and assign sequential captures [patterns[k][4]] = c3, }; if month_num[t.m] then -- when month not already a number t.m = month_num[t.m]; -- replace valid month name with a number else return nil, 'iso'; -- not a valid date form because month not valid end return mw.ustring.format ('%.4d-%.2d-%.2d', t.y, t.m, t.d), k; -- return date in iso format end end return nil, 'iso'; -- date could not be decoded; return nil and default iso date end --[[--------------------------< makeDate >----------------------- Given year, month, day numbers, (zero-padded or not) return a full date in df format where df may be one of: mdy, dmy, iso, ymd on entry, year, month, day are presumed to be correct for the date that they represent; all are required in this module, makeDate() is sometimes given an iso-format date in year: makeDate (2018-09-20, nil, nil, df) this works because table.concat() sees only one table member ]] local function makeDate (year, month, day, df) local format = { ['dmy'] = 'j F Y', ['mdy'] = 'F j, Y', ['ymd'] = 'Y F j', ['iso'] = 'Y-m-d', }; local date = table.concat ({year, month, day}, '-'); -- assemble year-initial numeric-format date (zero padding not required here) if non_western_digits then -- this wiki uses non-western digits? date = mw.ustring.gsub (date, '%d', digits); -- convert this wiki's non-western digits to western digits end return mw.getContentLanguage():formatDate (format[df], date); end --[[--------------------------< I S _ V A L I D _ D A T E >---------------------------------------------------- Returns true if date is after 31 December 1899 (why is 1900 the min year? shouldn't the internet's date-of-birth be min year?), not after today's date, and represents a valid date (29 February 2017 is not a valid date). Applies Gregorian leapyear rules. all arguments are required ]] local function is_valid_date (year, month, day) local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; local month_length; local y, m, d; local today = os.date ('*t'); -- fetch a table of current date parts if not year or == year or not month or == month or not day or == day then return false; -- something missing end y = tonumber (year); m = tonumber (month); d = tonumber (day); if 1900 > y or today.year < y or 1 > m or 12 < m then -- year and month are within bounds TODO: 1900? return false; end if (2==m) then -- if February month_length = 28; -- then 28 days unless if (0==(y%4) and (0~=(y%100) or 0==(y%400))) then -- is a leap year? month_length = 29; -- if leap year then 29 days in February end else month_length=days_in_month[m]; end if 1 > d or month_length < d then -- day is within bounds return false; end -- here when date parts represent a valid date return os.time({['year']=y, ['month']=m, ['day']=d, ['hour']=0}) <= os.time(); -- date at midnight must be less than or equal to current date/time end --[[--------------------------< decodeWebciteDate >----------------------- Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df format returns date string in df format - webcite date is a unix timestamp encoded as bae62 or the string 'query' ]] local function decodeWebciteDate(path, df) local dt = {}; local decode; dt = mw.text.split(path, "/") -- valid URL formats that are not base62 -- http://www.webcitation.org/query?id=1138911916587475 -- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03 -- http://www.webcitation.org/1138911916587475 -- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e -- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8e if dt[2]:find ('query', 1, true) or dt[2]:find ('cache', 1, true) or dt[2]:find ('getfile', 1, true) or tonumber(dt[2]) then return 'query'; end decode = base62(dt[2]); -- base62 string -> exponential number if not decode then return nil; -- nil return when dt[2] contains characters not in %w end dt = os.date('*t', string.format("%d", decode):sub(1,10)) -- exponential number -> text -> first 10 characters (a unix timestamp) -> a table of date parts decode = makeDate (dt.year, dt.month, dt.day, 'iso'); -- date comparisons are all done in iso format with western digits if non_western_digits then -- this wiki uses non-western digits? decode = mw.ustring.gsub (decode, '%d', digits); -- convert this wiki's non-western digits to western digits end return decode; end --[[--------------------------< decodeWaybackDate >----------------------- Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com ) or Library of Congress Web Archives (eg. /all/20160901010101/http://example.com) or UK Government Web Archive (eg. /ukgwa/20160901010101/http://example.com or /tna/20160901010101/http://example.com) return the formatted date eg. "September 1, 2016" in df format Handle non-digits in snapshot ID such as "re_" and "-" and "*" returns two values: first value is one of these: valid date string in df format - wayback date is valid (including the text string 'index' when date is '/*/') empty string - wayback date is malformed (less than 8 digits, not a valid date) nil - wayback date is '/save/' or otherwise not a number second return value is an appropriate 'message' may or may not be formatted ]] local function decodeWaybackDate(path, df) local msg, snapdate; snapdate = path:gsub ('^/web/', ):gsub ('^/all/', ):gsub ('^/ukgwa/', ):gsub ('^/tna/', ):gsub ('^/', ); -- remove leading /web/, /all/, /ukgwa/, /tna/, or / snapdate = snapdate:match ('^[^/]+'); -- get timestamp if snapdate == "*" then -- eg. /web/*/http.., etc. return 'index'; -- return indicator that this url has an index date end snapdate = snapdate:gsub ('%a%a_%d?$', ):gsub ('%-', ); -- from date, remove any trailing "re_", dashes msg = ; if snapdate:match ('%*$') then -- a trailing '*' causes calendar display at archive .org snapdate = snapdate:gsub ('%*$', ); -- remove so not part of length calc later msg = inlineRed (err_warn_msgs.ts_cal, 'warning'); -- make a message end if not tonumber(snapdate) then return nil, 'ts_nan'; -- return nil (fatal error flag) and message selector end local dlen = snapdate:len(); if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits? return , inlineRed (err_warn_msgs.ts_short, 'error'); -- return empty string and error message end local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here if not is_valid_date (year, month, day) then return , inlineRed (err_warn_msgs.ts_date, 'error'); -- return empty string and error message end snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format if 14 == dlen then return snapdate, msg; -- return date with message if any else return snapdate, msg .. inlineRed (err_warn_msgs.ts_len, 'warning'); -- return date with warning message(s) end end --[[--------------------------< decodeArchiveisDate >----------------------- Given an Archive.is "long link" URI-path (e.g. /2016.08.28-144552/http://example.com) return the date in df format (e.g. if df = dmy, return 28 August 2016) Handles "." and "-" in snapshot date, so 2016.08.28-144552 is same as 20160828144552 returns two values: first value is one of these: valid date string in df format - archive.is date is valid (including the text string 'short link' when url is the short form) empty string - wayback date is malformed (not a number, less than 8 digits, not a valid date) nil - wayback date is '/save/' second return value is an appropriate 'message' may or may not be formatted ]] local function decodeArchiveisDate(path, df) local snapdate if path:match ('^/%w+$') then -- short form url path is '/' followed by some number of base 62 digits and nothing else return "short link" -- e.g. http://archive.is/hD1qz end snapdate = mw.text.split (path, '/')[2]:gsub('[%.%-]', ); -- get snapshot date, e.g. 2016.08.28-144552; remove periods and hyphens local dlen = string.len(snapdate) if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits? return , inlineRed (err_warn_msgs.ts_short, 'error'); -- return empty string and error message end local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here if not is_valid_date (year, month, day) then return , inlineRed (err_warn_msgs.ts_date, 'error'); -- return empty string and error message end snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format if 14 == dlen then return snapdate; -- return date else return snapdate, inlineRed (err_warn_msgs.ts_len, 'warning'); -- return date with warning message end end --[[--------------------------< serviceName >----------------------- Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID ]] local function serviceName(host, no_link) local tracking; local index; host = host:lower():gsub ('^web%.(.+)', '%1'):gsub ('^www%.(.+)', '%1'); -- lowercase, remove web. and www. subdomains if services[host] then index = host; else for k, _ in pairs (services) do if host:find ('%f[%a]'..k:gsub ('([%.%-])', '%%%1')) then index = k; break; end end end if index then local out = {}; -- empty string in [1] so that concatenated result has leading single space ulx.url1.service = services[index][4] or 'other'; tracking = services[index][5] or categories.other; -- build tail string if false == services[index][1] then -- select prefix table.insert (out, prefixes.at); elseif true == services[index][1] then table.insert (out, prefixes.atthe); else table.insert (out, services[index][1]); end table.insert (out, make_wikilink (services[index][2], services[index][3], no_link)); -- add article wikilink if services[index][6] then -- add tail postfix if it exists table.insert (out, services[index][6]); end ulx.url1.tail = table.concat (out, ' '); -- put it all together; result has leading space character else -- here when unknown archive ulx.url1.service = 'other'; tracking = categories.unknown; ulx.url1.tail = table.concat ({, prefixes.at, host, inlineRed (err_warn_msgs.unknown_url, error)}, ' '); end track[tracking] = 1 end --[[--------------------------< parseExtraArgs >----------------------- Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10 For example: Template loop detected: Template:Webarchive Three url arguments not in numeric sequence (1..4..7). Function only processes arguments numbered 2 or greater (in this case 4 and 7) It creates numeric sequenced table entries like: urlx.url2.url = <argument value for url4> urlx.url3.url = <argument value for url7> Returns the number of URL arguments found numbered 2 or greater (in this case returns "2") ]] local function parseExtraArgs(args) local i, j, argurl, argurl2, argdate, argtitle j = 2 for i = 2, config.maxurls do argurl = "url" .. i if args[argurl] then argurl2 = "url" .. j ulx[argurl2] = {} ulx[argurl2]["url"] = args[argurl] argdate = "date" .. i if args[argdate] then ulx[argurl2]["date"] = args[argdate] else ulx[argurl2]["date"] = inlineRed (err_warn_msgs.date_miss, 'warning'); end argtitle = "title" .. i if args[argtitle] then ulx[argurl2]["title"] = args[argtitle] else ulx[argurl2]["title"] = nil end j = j + 1 end end if j == 2 then return 0 else return j - 2 end end --[[--------------------------< comma >----------------------- Given a date string, return "," if it's MDY ]] local function comma(date) return (date and date:match ('%a+ +%d%d?(,) +%d%d%d%d')) or ; end --[[--------------------------< createRendering >----------------------- Return a rendering of the data in ulx[][] ]] local function createRendering() local displayfield local out = {}; local index_date, msg = ulx.url1.date:match ('(index)(.*)'); -- when ulx.url1.date extract 'index' text and message text (if there is a message) ulx.url1.date = ulx.url1.date:gsub ('index.*', 'index'); -- remove message if 'none' == ulx.url1.format then -- For Template:Wayback, Template:Webcite table.insert (out, '['); -- open extlink markup table.insert (out, ulx.url1.url); -- add url if ulx.url1.title then table.insert (out, ' ') -- the required space table.insert (out, ulx.url1.title) -- the title table.insert (out, ']'); -- close extlink markup table.insert (out, ulx.url1.tail); -- tail text if ulx.url1.date then table.insert (out, ' ('); -- open date text; TODO: why the html entity? replace with regular space? table.insert (out, 'index' == ulx.url1.date and s_text.archive or s_text.archived); -- add text table.insert (out, ' '); -- insert a space table.insert (out, ulx.url1.date); -- add date table.insert (out, ')'); -- close date text end else -- no title if index_date then -- when url date is 'index' table.insert (out, table.concat ({' ', s_text.Archive_index, ']'})); -- add the index link label table.insert (out, msg or ); -- add date mismatch message when url date is /*/ and |date= has valid date else table.insert (out, table.concat ({' ', s_text.Archived, '] '})); -- add link label for url has timestamp date (will include mismatch message if there is one) end if ulx.url1.date then if 'index' ~= ulx.url1.date then table.insert (out, ulx.url1.date); -- add date when data is not 'index' end table.insert (out, comma(ulx.url1.date)); -- add ',' if date format is mdy table.insert (out, ulx.url1.tail); -- add tail text else -- no date table.insert (out, ulx.url1.tail); -- add tail text end end if 0 < ulx.url1.extraurls then -- For multiple archive URLs local tot = ulx.url1.extraurls + 1 table.insert (out, '.') -- terminate first url table.insert (out, table.concat ({' ', s_text.addlarchives, ': '})); -- add header text for i=2, tot do -- loop through the additionals local index = table.concat ({'url', i}); -- make an index displayfield = ulx[index]['title'] and 'title' or 'date'; -- choose display text table.insert (out, '['); -- open extlink markup table.insert (out, ulx[index]['url']); -- add the url table.insert (out, ' '); -- the required space table.insert (out, ulx[index][displayfield]); -- add the label table.insert (out, ']'); -- close extlink markup table.insert (out, i==tot and '.' or ', '); -- add terminator end end return table.concat (out); -- make a big string and done else -- For Template:Cite archives if 'addlarchives' == ulx.url1.format then -- Multiple archive services table.insert (out, table.concat ({s_text.addlarchives, ': '})); -- add header text else -- Multiple pages from the same archive table.insert (out, table.concat ({s_text.addlpages, ' '})); -- add header text table.insert (out, ulx.url1.date); -- add date to header text table.insert (out, ': '); -- close header text end local tot = ulx.url1.extraurls + 1; for i=1, tot do -- loop through the additionals local index = table.concat ({'url', i}); -- make an index table.insert (out, '['); -- open extlink markup table.insert (out, ulx[index]['url']); -- add url table.insert (out, ' '); -- add required space displayfield = ulx[index]['title']; if 'addlarchives' == ulx.url1.format then if not displayfield then displayfield = ulx[index]['date'] end else -- must be addlpages if not displayfield then displayfield = table.concat ({s_text.Page, ' ', i}); end end table.insert (out, displayfield); -- add title, date, page label text table.insert (out, ']'); -- close extlink markup table.insert (out, (i==tot and '.' or ', ')); -- add terminator end return table.concat (out); -- make a big string and done end end --[[--------------------------< P A R A M E T E R _ N A M E _ X L A T E >-------------------------------------- for internaltionalization, translate local-language parameter names to their English equivalents TODO: return error message if multiple aliases of the same canonical parameter name are found? returns two tables: new_args - holds canonical form parameters and their values either from translation or because the parameter was already in canonical form origin - maps canonical-form parameter names to their untranslated (local language) form for error messaging in the local language unrecognized parameters are ignored ]] local function parameter_name_xlate (args, params, enum_params) local name; -- holds modifiable name of the parameter name during evaluation local enum; -- for enumerated parameters, holds the enumerator during evaluation local found = false; -- flag used to break out of nested for loops local new_args = {}; -- a table that holds canonical and translated parameter k/v pairs local origin = {}; -- a table that maps original (local language) parameter names to their canonical name for local language error messaging local unnamed_params; -- set true when unsupported positional parameters are detected for k, v in pairs (args) do -- loop through all of the arguments in the args table name = k; -- copy of original parameter name if 'string' == type (k) then if non_western_digits then -- true when non-western digits supported at this wiki name = mw.ustring.gsub (name, '%d', digits); -- convert this wiki's non-western digits to western digits end enum = name:match ('%d+$'); -- get parameter enumerator if it exists; nil else if not enum then -- no enumerator so looking for non-enumnerated parameters -- TODO: insert shortcut here? if params[name] then name holds the canonical parameter name; no need to search further for pname, aliases in pairs (params) do -- loop through each parameter the params table for _, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table if name == alias then new_args[pname] = v; -- create a new entry in the new_args table origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name found = true; -- flag so that we can break out of these nested for loops break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair end end if found then -- true when we found an alias that matched name found = false; -- reset the flag break; -- go do next args k/v pair end end else -- enumerated parameters name = name:gsub ('%d$', '#'); -- replace enumeration digits with place holder for table search -- TODO: insert shortcut here? if num_params[name] then name holds the canonical parameter name; no need to search further for pname, aliases in pairs (enum_params) do -- loop through each parameter the num_params table for _, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table if name == alias then pname = pname:gsub ('#$', enum); -- replace the '#' place holder with the actual enumerator new_args[pname] = v; -- create a new entry in the new_args table origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name found = true; -- flag so that we can break out of these nested for loops break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair end end if found then -- true when we found an alias that matched name found = false; -- reset the flag break; -- go do next args k/v pair end end end else unnamed_params = true; -- flag for unsupported positional parameters end end -- for k, v return new_args, origin, unnamed_params; end --[[--------------------------< W E B A R C H I V E >---------------------------------------------------------- template entry point ]] local function webarchive(frame) local args = getArgs (frame); local data = mw.loadData (table.concat ({ -- make a data module name; sandbox or live 'Module:Webarchive/data', frame:getTitle():find('sandbox', 1, true) and '/sandbox' or -- this instance is ./sandbox then append /sandbox })); categories = data.categories; -- fill in the forward declarations config = data.config; if data.digits.enable then digits = data.digits; -- for i18n; table of digits in the local wiki's language non_western_digits = true; -- use_non_western_digits end err_warn_msgs = data.err_warn_msgs; excepted_pages = data.excepted_pages; month_num = data.month_num; -- for i18n; table of month names in the local wiki's language prefixes = data.prefixes; services = data.services; s_text = data.s_text; uncategorized_namespaces = data.uncategorized_namespaces; uncategorized_subpages = data.uncategorized_subpages; local origin = {}; -- holds a map of English to local language parameter names used in the current template; not currently used local unnamed_params; -- boolean set to true when template call has unnamed parameters args, origin, unnamed_params = parameter_name_xlate (args, data.params, data.enum_params); -- translate parameter names in args to English local date, format, msg, udate, uri, url; local ldf = 'iso'; -- when there is no |date= parameter, render url dates in iso format if args.url and args.url1 then -- URL argument (first) return inlineError (data.crit_err_msgs.conflicting, {origin.url, origin.url1}); end url = args.url or args.url1; if not url then return inlineError (data.crit_err_msgs.empty); end -- these iabot bugs perportedly fixed; removing these causes lua script error --[[ -- at Template:Webarchive/testcases/Production; resolve that before deleting these tests if mw.ustring.find( url, "https://web.http", 1, true ) then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred track[categories.error] = 1; return inlineError (data.crit_err_msgs.iabot1); end if url == "https://web.archive.org/http:/" then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred track[categories.error] = 1; return inlineError (data.crit_err_msgs.iabot2); end ]] if not (url:lower():find ('^http') or url:find ('^//')) then return inlineError (data.crit_err_msgs.invalid_url ); end ulx.url1 = {} ulx.url1.url = url ulx.url1.extraurls = parseExtraArgs(args) local good = false; good, uri = pcall (mw.uri.new, ulx.url1.url); -- get a table of uri parts from this url; protected mode to prevent lua error when ulx.url1.url is malformed if not good or nil == uri.host then -- abandon when ulx.url1.url is malformed return inlineError (data.crit_err_msgs.invalid_url); end serviceName(uri.host, args.nolink) if args.date and args.date1 then -- Date argument return inlineError (data.crit_err_msgs.conflicting, {origin.date, origin.date1}); end date = args.date or args.date1; date = date and date:gsub (' +', ' '); -- replace multiple spaces with a single space if date and config.verifydates then if '*' == date then date = 'index'; ldf = 'iso'; -- set to default format elseif 'mdy' == date then date = nil; -- if date extracted from URL, ldf = 'mdy'; -- then |date=mdy overrides iso elseif 'dmy' == date then date = nil; -- if date extracted from URL, ldf = 'dmy'; -- then |date=dmy overrides iso elseif 'ymd' == date then date = nil; -- if date extracted from URL, ldf = 'ymd'; -- then |date=ymd overrides iso else date, ldf = decode_date (date); -- get an iso format date from date and get date's original format end end if 'wayback' == ulx.url1.service or 'locwebarchives' == ulx.url1.service or 'ukgwa' == ulx.url1.service then if date then if config.verifydates then if ldf then udate, msg = decodeWaybackDate (uri.path); -- get the url date in iso format and format of date in |date=; 'index' when wayback url date is * if not udate then -- this is the only 'fatal' error return return inlineError (data.crit_err_msgs[msg]); end if udate ~= date then -- date comparison using iso format dates date = udate; msg = table.concat ({ inlineRed (err_warn_msgs.mismatch, 'warning'), -- add warning message msg, -- add message if there is one }); end end end else -- no |date= udate, msg = decodeWaybackDate (uri.path); if not udate then -- this is the only 'fatal' error return return inlineError (data.crit_err_msgs[msg]); end if == udate then date = nil; -- unset else date = udate; end end elseif 'webcite' == ulx.url1.service then if date then if config.verifydates then if ldf then udate = decodeWebciteDate (uri.path); -- get the url date in iso format if 'query' ~= udate then -- skip if query if udate ~= date then -- date comparison using iso format dates date = udate; msg = table.concat ({ inlineRed (err_warn_msgs.mismatch, 'warning'), }); end end end end else date = decodeWebciteDate( uri.path, "iso" ) if date == "query" then date = nil; -- unset msg = inlineRed (err_warn_msgs.date_miss, 'warning'); elseif not date then -- invalid base62 string date = inlineRed (err_warn_msgs.date1, 'error'); end end elseif 'archiveis' == ulx.url1.service then if date then if config.verifydates then if ldf then udate, msg = decodeArchiveisDate (uri.path) -- get the url date in iso format if 'short link' ~= udate then -- skip if short link if udate ~= date then -- date comparison using iso format dates date = udate; msg = table.concat ({ inlineRed (err_warn_msgs.mismatch, 'warning'), -- add warning message msg, -- add message if there is one }); end end end end else -- no |date= udate, msg = decodeArchiveisDate( uri.path, "iso" ) if udate == "short link" then date = nil; -- unset msg = inlineRed (err_warn_msgs.date_miss, 'warning'); elseif == udate then date = nil; -- unset else date = udate; end end else -- some other service if not date then msg = inlineRed (err_warn_msgs.date_miss, 'warning'); end end if 'index' == date then ulx.url1.date = date .. (msg or ); -- create index + message (if there is one) elseif date then ulx.url1.date = makeDate (date, nil, nil, ldf) .. (msg or ); -- create a date in the wiki's local language + message (if there is one) else ulx.url1.date = msg; end format = args.format; -- Format argument if not format then format = "none" else for k, v in pairs (data.format_vals) do -- |format= accepts two specific values loop through a table of those values local found; -- declare a nil flag for _, p in ipairs (v) do -- loop through local language variants if format == p then -- when |format= value matches format = k; -- use name from table key found = true; -- declare found so that we can break out of outer for loop break; -- break out of inner for loop end end if found then break; end end if format == "addlpages" then if not ulx.url1.date then format = "none" end elseif format == "addlarchives" then format = "addlarchives" else format = "none" end end ulx.url1.format = format if args.title and args.title1 then -- Title argument return inlineError (data.crit_err_msgs.conflicting, {origin.title, origin.title1}); end ulx.url1.title = args.title or args.title1; local rend = createRendering() if not rend then return inlineError (data.crit_err_msgs.unknown); end return rend .. ((unnamed_params and inlineRed (err_warn_msgs.unnamed_params, 'warning')) or ) .. createTracking(); end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return {webarchive = webarchive};
- ↑ Eggertsen, Chris (November 4, 2016). CARRIE's Prom Scene: An Oral History (Part Two). Retrieved on September 13, 2017.
- ↑ Sears, John: Stephen King's Gothic (2011) 978-0-7083-2402-8 p. 31
- ↑ "Carrie- Original Motion Picture Soundtrack LP". Retrieved on July 11, 2017.
- ↑ Carrie [Original Motion Picture Soundtrack: Releases]. All Media Network, LLC. Retrieved on July 11, 2017.
- ↑ Special 2-CD soundtrack "Carrie" full score composed by Pino Donaggio. kritzerland.com. Retrieved on August 3, 2013.
- ↑ 21.0 21.1 Template:Cite magazine
- ↑ Template:PAGENAMEBASE at the American Film Institute CatalogScript error: No such module "EditAtWikidata".
- ↑ Greatest Films of 1976. Filmsite.org. Retrieved on October 2, 2012.
- ↑ The Best Movies of 1976 by Rank. Films101.com. Retrieved on October 2, 2012.
- ↑ IMDb: Year: 1976.
- ↑ Carrie (1976). Rotten Tomatoes. Fandango. Retrieved on April 22, 2019.
- ↑ Carrie Reviews. Metacritic. CBS Interactive. Retrieved on April 5, 2019.
- ↑ Ebert, Roger. Roger Ebert (Chicago Sun Times) Review of Carrie (1976). Retrieved May 27, 2007.
- ↑ Take One Magazine, January 1977 at Carrie... A Fan's Site
- ↑ 30.0 30.1 Pundits Page. Take One Magazine, p.57 (March 1997).
- ↑ Quentin Tarantino's Handwritten List of the 11 Greatest Movies. Empire (2008). Retrieved on October 2, 2013.
- ↑ Siskel, Gene (November 9, 1976). "'Carrie' has style but violence carries the day". Chicago Tribune. Section 2, p. 7.
- ↑ Template:Cite magazine
- ↑ Richard Nowell, Blood Money: A History of the First Teen Slasher Film Cycle Continuum, 2011 p 256
- ↑ Template:Cite magazine
- ↑ AFI's 100 Years ... 100 Thrills. American Film Institute. Retrieved on March 7, 2012.
- ↑ AFI's 100 Years... 100 Heroes and Villains. American Film Institute. Retrieved on October 25, 2018.
- ↑ TV Reviews: "Carrie" (November 4, 2002).
- ↑ Kit, Borys. "MGM, Screen Gems Team for 'Carrie' Remake", The Hollywood Reporter, May 19, 2011.
- ↑ Template:Cite magazine
- ↑ Julianne Moore And Gabriella Wilde Board Carrie Remake. CinemaBlend.com (May 14, 2012). Retrieved on October 2, 2012.
- ↑ "Chronicle" star Alex Russell and Broadway actor Ansel Elgort join "Carrie" remake opposite Chloe Moretz. Up and Comers. Retrieved on October 2, 2012.
- ↑ UPDATE: Judy Greer HAS NOT Signed On To The Carrie Remake As The Gym Teacher. CinemaBlend.com (May 25, 2012). Retrieved on October 2, 2012.
- ↑ Template:Cite magazine
- ↑ Schulman, Michael. "Is 'Carrie' the Worst Musical of All Time?", January 27, 2012. Retrieved on April 3, 2017.
- ↑ Eric Jackson Interview. horrorking.com. Retrieved on February 27, 2008.
- ↑ "New York Times Theater Review", The New York Times, November 26, 2006. Retrieved on February 27, 2008.
- ↑ Hell in a Handbag's Scarrie site. handbagproductions.org. Retrieved on February 27, 2008.
- ↑ Sci-Fi Dimensions Review. scifidimensions. Archived from the original on March 6, 2008. Retrieved on February 27, 2008.
- ↑ Carrie's Facts of Life – Official Site. norunningwithscissors.com. Retrieved on February 27, 2008.
- ↑ Template:Cite magazine
- ↑ Carrie DVD. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie DVD: Special Edition. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie DVD: Decades Collection with CD / DVD + CD. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ 55.0 55.1 Carrie Triple Feature DVD. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie: 2-Pack Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie w/ Collectible Halloween Faceplate Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie Blu-ray: Collector's Edition. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie Blu-ray: Shout Factory Exclusive / Deluxe Limited Edition. Blu-ray.com. Retrieved on September 30, 2017.
- ↑ Carrie (Special Edition) [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
- ↑ CARRIE [DVD]. Amazon.co.uk. Retrieved on September 30, 2017.
- ↑ Carrie / The Rage: Carrie 2 Double Pack [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
- ↑ Carrie [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
- ↑ Carrie [Blu-ray [1976]]. Retrieved on September 30, 2017.
- ↑ Carrie (FuturePak) [Blu-ray]. Retrieved on September 30, 2017.
- ↑ Carrie – Limited Edition. Arrow Films. Retrieved on September 30, 2017.
- ↑ Squires, JohnArrow Video Bringing 4K Restoration of Original 'Carrie' to Blu-ray. Bloody Disgusting (22 December 2017). Retrieved on September 30, 2017.
Further reading[]
- Ehlers, Leigh A. "Carrie: Book and film." Literature/Film Quarterly 9.1 (1981): 32–39.
- Shih, Paris Shun-Hsiang. "Fearing the Witch, Hating the Bitch: The Double Structure of Misogyny in Stephen King’s Carrie." in Perceiving Evil: Evil Women and the Feminine (Brill, 2015) pp. 49–58.
- Tibbetts, John C., and James M. Welsh, eds. The Encyclopedia of Novels Into Film (2nd ed. 2005) pp 49–50.
External links[]
Template:Wikiquote
Lua error: bad argument #2 to 'title.new' (unrecognized namespace name 'Portal').
- Template:PAGENAMEBASE at the American Film Institute CatalogScript error: No such module "EditAtWikidata".
- Template:Mojo title
- Carrie at the Internet Movie Database (IMDb)
- Template:Rotten-tomatoes
Template:Carrie Template:Media based on Stephen King works Template:Brian De Palma Template:Authority control