Wikipedia:Reference desk/Computing
of the Wikipedia reference desk.
Main page: Help searching Wikipedia
How can I get my question answered?
- Select the section of the desk that best fits the general topic of your question (see the navigation column to the right).
- Post your question to only one section, providing a short header that gives the topic of your question.
- Type '~~~~' (that is, four tilde characters) at the end – this signs and dates your contribution so we know who wrote what and when.
- Don't post personal contact information – it will be removed. Any answers will be provided here.
- Please be as specific as possible, and include all relevant context – the usefulness of answers may depend on the context.
- Note:
- We don't answer (and may remove) questions that require medical diagnosis or legal advice.
- We don't answer requests for opinions, predictions or debate.
- We don't do your homework for you, though we'll help you past the stuck point.
- We don't conduct original research or provide a free source of ideas, but we'll help you find information you need.
How do I answer a question?
Main page: Wikipedia:Reference desk/Guidelines
- The best answers address the question directly, and back up facts with wikilinks and links to sources. Do not edit others' comments and do not give any medical or legal advice.
October 29
[edit]https
[edit]How to http: and https: relate these days?
If a server prefers https, and I follow a link that has http:, the server will (always?) substitute https:. But what about the reverse? Not all websites have made the change. Will a http site do the right thing with a https: address? —Antonissimo (talk) 03:37, 29 October 2026 (UTC)
- See Transport Layer Security (TLS). This is the underlying tech that maintains privacy for the communication between a user's computer and the server. While some servers are configured to allow unencrypted (plain http) mode as fallback, doing so has security implications: this would make a man-in-the-middle attack feasible. For example, attacker eavesdropping on a user's connection half-way, taking the HTTPS request packet, and do something to it to make it fail to force a fallback to plain HTTP. 海盐沙冰 / aka irisChronomia / Talk / Uploads 05:29, 29 October 2026 (UTC)
- The automated upgrade from http: to https: may be due to your browser, rather than the server. ‑‑Lambiam 08:21, 29 October 2026 (UTC)
- It can also be in a router and corporate packet inspection. From the browser to the web server, there is long-standing history of automatically converting http traffic to https without asking the user.
- But, I wanted to answer the question about how they relate. If you use http, your web request is unencrypted in transit. If you use https, your web request (the same request you made in http) is encrypted in transit. The standard format of encryption is TLS. What is important here is not that it is encrypted from your computer to the server. It is encrypted from your web browser to the web service running on the web server.
- I also wanted to respond to the statement that not all website have made the change. That is true. It is expensive to implement https because you need a secure certificate on the server. You either pay in money or time. For around $1000, you can easily purchase a certificate that lasts years. For $0, you can spend hours fiddling with cryptic broken websites to try and get a certificate that lasts a few months and then you have to start over again, trying to run through the maze of more broken links, broken forms, and broken instructions... and tons of advertising that covers up that one button you were supposed to click five screens ago. Therefore, if you don't feel you need encryption on your website, why deal with it? ~2026-46630-01 (talk) 11:50, 29 October 2026 (UTC)
October 31
[edit]Diagram explaining PHP2Shell
[edit]Would https://www.akamai.com/blog/security-research/understanding-php2shell-everything-you-need-to-know and https://outcomeschool.com/blog/php2shell be considered reputable sources if I wish to draw a diagram explaining how PHP2Shell works, in a similar style to this explanation for Heartbleed? cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 00:13, 31 October 2026 (UTC)
- Akamai Technologies is a reputable company with long-standing expertise in the area of cybersecurity, so I think it can be considered a reliable source. I have no reason to doubt the accuracy of the explanation on the website of Outcome School by its founder, Amit Shekhar, a graduate of IIT (BHU) Varanasi. This school is a prestigious engineering institution, but I do not have evidence that Amit Shekhar has specific cybersecurity expertise, so it is less clear that this page can be considered a "reliable source" in the specific Wikipedia sense. As it aims at a more general public, it may still be a valuable resource in understanding the more detailed technical explanation on Akamai's security blog and condensing it to a simple diagram. CVE-2026-109619 is essentially a dangling pointer issue, so the (static) diagram in the article Dangling pointer may, perhaps, also be a source of inspiration. ‑‑Lambiam 11:53, 31 October 2026 (UTC)
- I have thought about this because I've had to explain the PHP2Shell bug. The issue is that most people don't have a good feel for how the server handles multiple requests. So, the explanation is a lot of handwaving. What you really need is a non-computer scenario where an order is placed in a slot of some kind and that order is marked active/inactive. Under normal conditions, the order comes in. It gets marked active. The order is completed. It gets marked inactive. The slot is cleared. The PHP2Shell scenario is an order comes in. The slot is marked active. The order fails and the slot is cleared (this is the bug: the slot should be marked inactive as well). Then, an order for something you shouldn't be allowed to order is put into that slot. It is active, so the order is completed, the slot is marked inactive, and the slot is cleared. What is expected is that the illegal order comes in, the slot is checked, it is illegal, blocked. But, because the previous failed order left the slot active, the illegal order is assumed to have been checked. In my mind, I think it can relate to a diner run by simplistic robots following command loops. A customer orders 999 hamburgers. It fails. The customer orders $200 and the order is fulfilled. ~2026-46630-01 (talk) 14:05, 2 November 2026 (UTC)
- I've been thinking about this further and while my previous example shows how an error in error handling can allow access to things the user shouldn't access, the description is wrong. In PHP2Shell, the big issue is that memory is marked "available" but is not cleared. So, to make it something physical, memory should be trays (for some reason). Users ask for something. A tray is marked "in use" and something is put on the tray. The user gets what their stuff and returns the empty tray which is marked "available." What if there is an error in filling a tray? It SHOULD empty the tray and mark it as available. The PHP2Shell bug was that it marked the tray "available" without emptying it, so the next person to use that tray would get not only what they asked for but whatever was still sitting on the tray. There are many ways to exploit that in real-world scenarios like a betting station or a sushi bar or a mailbox system... ~2026-46630-01 (talk) 13:46, 9 November 2026 (UTC)
November 8
[edit]Split a string at spaces into n roughly equal-length strings
[edit]In a translation project, I would like to translate labels into many different languages. The number of rows of text in each label is fixed but the number of words (delimited by spaces) in the translation is variable. As the Python script cannot tell how wide characters are, assume that each character is the same width (monospace). Instead of linewrapping to a fixed length, I prefer to make each row approximately the same length.
Can someone please describe an algorithm (preferably in python Python 2 with standard libraries) that can split a string into n roughly equal parts at its spaces? If there are fewer than n−1 spaces, the number of rows is reduced (it doesn't hyphenate).
A naive way is to wrap the text at spaces to lines of at most string length/number of rows needed characters. That would fail with, say, "AAAAA B CCCCC DDDD". Ignoring spaces, the length is 15. For 3 rows, the ratio is 5, thus the first row output is "AAAAA". As "B CCCCC" also exceeds 5, the second row output is "B", leaving "CCCCC DDDD" on the third. It should output either "AAAAA B`CCCCC`DDDD" or "AAAAA`B CCCCC`DDDD" ("`" denote hard returns) instead.
An alternative is to brute-force all partitions and choose the one with lowest maximum row length. However, with, say, 10 words and 3 rows, one has to check 120 combinations. Is there a more efficient way?
Thanks, cmɢʟee τaʟκ (please add {{ping|cmglee}} to your reply) 13:01, 8 November 2026 (UTC)
- The best partition according to some criterion can be computed in quadratic time, using dynamic programming. Think of the potential split points as nodes in a graph, including the point at the start and that at the end of the string. For the string "AA B" of 4 symbols (we treat a space as a symbol) we get something like
- •A•A• •B•,
- with 5 nodes. The graph is directed, with an edge running from each node to each later node. For n nodes, there are 1⁄2 n (n − 1) edges.
- Each edge has a non-negative weight, representing an edge cost, and the idea is to find the cheapest path from the starting point to the end point, that is, with least total path cost. This problem is an instance of the shortest path problem in a directed graphs with nonnegative weights (reading "cost" for "length" and "cheapest" for "shortest"), but slightly simpler because the nodes are already topologically sorted. Each edge corresponds to a string segment, and the path determines a partition. A segment that is too long to fit has a very high edge cost, say +∞, so that no path will be selected with such a segment. A segment that fits precisely gets edge cost 0. A segment that fits but leaves space gets a real edge cost, depending on how much slack it leaves. One cost measure is the length s of the slack, which will tend to minimize the number of rows. Another measure is s2, which I expect to be esthetically more pleasing. A compromise between these desirable properties is obtained by adding the measures: s + s2.
- Edges corresponding to segments of only blank space will be treated differently in the final phase. When turning the partition into a sequence of rows, they must be skipped. Their edge cost is 0.
- The algorithm determines, from right to left, the path cost of the cheapest path from each node to the end point, labelling the node with the path cost. Let the nodes be numbered from 0 to n.
- The path from node n to itself is the null path; it has path cost 0. For node i < n, each path from that node to n consists of a first edge from i to a node j < n, followed by a path from j to n. In the cheapest path from i, the path from the next node j will also be a cheapest path. So the path cost of the cheapest path from i to n is equal to
- min i +1 ≤ j ≤ n edgecost(i, j) + pathcost(j).
- Whenever, in a loop considering j = i + 1, j = i + 2, ..., the value of edgecost(i, j) reaches +∞, the loop can be broken prematurely, since nothing further on will be any good. This will effectively make the algorithm linear time.
- After this right-to-left scan, we are positioned to determine the optimal partitioning in a left-to-right scan; the same loop can immediately produce the output.
- Set i equal to 0. Then, while i < n, repeat:
- Find j > i such that
- edgecost(i, j) + pathcost(j) = pathcost(i).
- Output segment edge(i, j), unless totally blank.
- Set i equal to j.
- Find j > i such that
- ‑‑Lambiam 10:29, 9 November 2026 (UTC)
- I suggest looking at the Knuth–Plass line-breaking algorithm. ~2026-46630-01 (talk) 13:40, 9 November 2026 (UTC)
- The above is basically a simplified (and arguably higher-level) description of that algorithm, with the innovation of starting with a right-to-left scan. ‑‑Lambiam 21:18, 9 November 2026 (UTC)
- Thank you very much, Lambiam. In case it's useful to anyone else, I've used dynamic programming to implement the auto-wrapping below. cmɢʟee τaʟκ (please add
{{ping|cmglee}}to your reply) 12:34, 10 November 2026 (UTC) def split_to_rows(text, n_row): ## split text to up to n_row roughly equal rows words = text.split() n_word = len(words) if n_word <= n_row: return words i_char_breaks = [0] for word in words: i_char_breaks.append(i_char_breaks[-1] + len(word)) ## segment_length returns length of words[i:j] when joined with single spaces def segment_length(i,j): return i_char_breaks[j] - i_char_breaks[i] + j - i - 1 target = float(segment_length(0, n_word)) / n_row ## costss[k][j] = minimum cost to split the first j words into k parts previous_cutss = [[ None ] * (n_word + 1) for k in range(n_row + 1)] costss = [[float('inf')] * (n_word + 1) for k in range(n_row + 1)] costss[0][0] = 0.0 for k in range(1,n_row + 1): for j in range(k,n_word - (n_row - k) + 1): ## j leaves >=1 word in each part for i in range(k - 1,j): length = segment_length(i,j) cost = costss[k - 1][i] + (length - target) ** 2 if cost < costss[k][j]: (costss[k][j], previous_cutss[k][j]) = (cost, i) ## Reconstruct the chosen parts (cuts, j) = ([n_word], n_word) for k in range(n_row, 0, -1): j = previous_cutss[k][j] cuts.append(j) return [' '.join(words[cuts[-(k + 1)]:cuts[-(k + 2)]]) for k in range(n_row)] def split_to_row(text, n_row): return CR.join(split_to_rows(text, n_row))
- Thank you very much, Lambiam. In case it's useful to anyone else, I've used dynamic programming to implement the auto-wrapping below. cmɢʟee τaʟκ (please add
- The above is basically a simplified (and arguably higher-level) description of that algorithm, with the innovation of starting with a right-to-left scan. ‑‑Lambiam 21:18, 9 November 2026 (UTC)
- Sometimes, brute force is a lot less complicated:
- Alien878 (talk) 14:21, 10 November 2026 (UTC)
:import textwrap :my_text = 'asdf asdffasdf asdf asdf asdfsdfasdf asdf asdfasdfasdf asdfa asdf' * 10 :target_number_of_lines = 8 :max_width = 200 :text_list = None :# Try wrapping with increasing widths until we get the right number of lines :for width in range(1, max_width): : text_list = textwrap.wrap(my_text, width) : if len(text_list) <= target_number_of_lines: : break :if text_list is not None: : print('\n'.join(text_list)) :else: : print(f'Text requires greater than {max_width}') :
- @Alien878: Clever idea, thanks! cmɢʟee τaʟκ (please add
{{ping|cmglee}}to your reply) 02:51, 11 November 2026 (UTC)
- @Alien878: Clever idea, thanks! cmɢʟee τaʟκ (please add